* [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 14:33 ` Frank Li
2026-03-31 7:23 ` [RFC PATCH 2/7] docs: " ming.qian
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
applications to query the total amount of memory currently used
by a device instance.
This control reports the memory consumption in bytes, including
internal buffers, intermediate processing data, and other
driver-managed allocations. Applications can use this information
for debugging, resource monitoring, or making informed decisions
about buffer allocation strategies.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
include/uapi/linux/v4l2-controls.h | 4 +++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
index 551426c4cd01..053db78ff661 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
@@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB";
+ case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
/*
* Codec controls
@@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
*min = 0;
*max = 0xffff;
break;
+ case V4L2_CID_MEMORY_USAGE:
+ *type = V4L2_CTRL_TYPE_INTEGER64;
+ *flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ *min = 0;
+ *max = S64_MAX;
+ *step = 1;
+ break;
case V4L2_CID_FLASH_FAULT:
case V4L2_CID_JPEG_ACTIVE_MARKER:
case V4L2_CID_3A_LOCK:
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 68dd0c4e47b2..02c6f960d38e 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -110,8 +110,10 @@ enum v4l2_colorfx {
#define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
#define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
+#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
+
/* last CID + 1 */
-#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
+#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
/* USER-class private control IDs */
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 7:23 ` [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control ming.qian
@ 2026-03-31 14:33 ` Frank Li
2026-03-31 14:54 ` Nicolas Dufresne
2026-04-01 2:07 ` Ming Qian(OSS)
0 siblings, 2 replies; 16+ messages in thread
From: Frank Li @ 2026-03-31 14:33 UTC (permalink / raw)
To: ming.qian
Cc: linux-media, mchehab, hverkuil-cisco, nicolas, sebastian.fricke,
shawnguo, s.hauer, kernel, festevam, linux-imx, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
> From: Ming Qian <ming.qian@oss.nxp.com>
>
> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
> applications to query the total amount of memory currently used
> by a device instance.
>
> This control reports the memory consumption in bytes, including
> internal buffers, intermediate processing data, and other
> driver-managed allocations. Applications can use this information
> for debugging, resource monitoring, or making informed decisions
> about buffer allocation strategies.
>
> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
> ---
Not sure why not export these information by debugfs, or any benefit vs
debugfs?
Generanlly document should be first patch, then driver change.
Frank
> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
> include/uapi/linux/v4l2-controls.h | 4 +++-
> 2 files changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> index 551426c4cd01..053db78ff661 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
> case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
> case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
> case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB";
> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>
> /*
> * Codec controls
> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> *min = 0;
> *max = 0xffff;
> break;
> + case V4L2_CID_MEMORY_USAGE:
> + *type = V4L2_CTRL_TYPE_INTEGER64;
> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
> + *min = 0;
> + *max = S64_MAX;
> + *step = 1;
> + break;
> case V4L2_CID_FLASH_FAULT:
> case V4L2_CID_JPEG_ACTIVE_MARKER:
> case V4L2_CID_3A_LOCK:
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 68dd0c4e47b2..02c6f960d38e 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>
> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
> +
> /* last CID + 1 */
> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>
> /* USER-class private control IDs */
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 14:33 ` Frank Li
@ 2026-03-31 14:54 ` Nicolas Dufresne
2026-04-01 2:23 ` Ming Qian(OSS)
2026-04-01 2:07 ` Ming Qian(OSS)
1 sibling, 1 reply; 16+ messages in thread
From: Nicolas Dufresne @ 2026-03-31 14:54 UTC (permalink / raw)
To: Frank Li, ming.qian
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 3043 bytes --]
Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
> On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
> > From: Ming Qian <ming.qian@oss.nxp.com>
> >
> > Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
> > applications to query the total amount of memory currently used
> > by a device instance.
> >
> > This control reports the memory consumption in bytes, including
> > internal buffers, intermediate processing data, and other
> > driver-managed allocations. Applications can use this information
> > for debugging, resource monitoring, or making informed decisions
> > about buffer allocation strategies.
> >
> > Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
> > ---
>
> Not sure why not export these information by debugfs, or any benefit vs
> debugfs?
There is also a on-going proposal that uses fdinfo.
Nicolas
>
> Generanlly document should be first patch, then driver change.
>
> Frank
>
> > drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
> > include/uapi/linux/v4l2-controls.h | 4 +++-
> > 2 files changed, 11 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> > index 551426c4cd01..053db78ff661 100644
> > --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> > +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> > @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
> > case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
> > case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
> > case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB";
> > + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
> >
> > /*
> > * Codec controls
> > @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> > *min = 0;
> > *max = 0xffff;
> > break;
> > + case V4L2_CID_MEMORY_USAGE:
> > + *type = V4L2_CTRL_TYPE_INTEGER64;
> > + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > + *min = 0;
> > + *max = S64_MAX;
> > + *step = 1;
> > + break;
> > case V4L2_CID_FLASH_FAULT:
> > case V4L2_CID_JPEG_ACTIVE_MARKER:
> > case V4L2_CID_3A_LOCK:
> > diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> > index 68dd0c4e47b2..02c6f960d38e 100644
> > --- a/include/uapi/linux/v4l2-controls.h
> > +++ b/include/uapi/linux/v4l2-controls.h
> > @@ -110,8 +110,10 @@ enum v4l2_colorfx {
> > #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
> > #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
> >
> > +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
> > +
> > /* last CID + 1 */
> > -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
> > +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
> >
> > /* USER-class private control IDs */
> >
> > --
> > 2.53.0
> >
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 14:54 ` Nicolas Dufresne
@ 2026-04-01 2:23 ` Ming Qian(OSS)
2026-04-02 3:14 ` Ming Qian(OSS)
0 siblings, 1 reply; 16+ messages in thread
From: Ming Qian(OSS) @ 2026-04-01 2:23 UTC (permalink / raw)
To: Nicolas Dufresne, Frank Li
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
Hi Nicolas,
On 3/31/2026 10:54 PM, Nicolas Dufresne wrote:
> Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
>> On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
>>> From: Ming Qian <ming.qian@oss.nxp.com>
>>>
>>> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
>>> applications to query the total amount of memory currently used
>>> by a device instance.
>>>
>>> This control reports the memory consumption in bytes, including
>>> internal buffers, intermediate processing data, and other
>>> driver-managed allocations. Applications can use this information
>>> for debugging, resource monitoring, or making informed decisions
>>> about buffer allocation strategies.
>>>
>>> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
>>> ---
>>
>> Not sure why not export these information by debugfs, or any benefit vs
>> debugfs?
>
> There is also a on-going proposal that uses fdinfo.
>
> Nicolas
>
Thanks for the reminder about the ongoing fdinfo proposal.
Just to confirm, you are referring to Detlev’s ongoing fdinfo proposal,
specifically this series:
https://lore.kernel.org/lkml/20260212162328.192217-1-detlev.casanova@collabora.com/
I will align my work with it and switch to using fdinfo.
Once the show_fdinfo support from that series is merged, I will prepare
the next revision of my patch accordingly.
Regards,
Ming
>>
>> Generanlly document should be first patch, then driver change.
>>
>> Frank
>>
>>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
>>> include/uapi/linux/v4l2-controls.h | 4 +++-
>>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>> index 551426c4cd01..053db78ff661 100644
>>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>>> case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
>>> case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
>>> case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB";
>>> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>>>
>>> /*
>>> * Codec controls
>>> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>>> *min = 0;
>>> *max = 0xffff;
>>> break;
>>> + case V4L2_CID_MEMORY_USAGE:
>>> + *type = V4L2_CTRL_TYPE_INTEGER64;
>>> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>> + *min = 0;
>>> + *max = S64_MAX;
>>> + *step = 1;
>>> + break;
>>> case V4L2_CID_FLASH_FAULT:
>>> case V4L2_CID_JPEG_ACTIVE_MARKER:
>>> case V4L2_CID_3A_LOCK:
>>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
>>> index 68dd0c4e47b2..02c6f960d38e 100644
>>> --- a/include/uapi/linux/v4l2-controls.h
>>> +++ b/include/uapi/linux/v4l2-controls.h
>>> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
>>> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
>>> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>>>
>>> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
>>> +
>>> /* last CID + 1 */
>>> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
>>> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>>>
>>> /* USER-class private control IDs */
>>>
>>> --
>>> 2.53.0
>>>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-04-01 2:23 ` Ming Qian(OSS)
@ 2026-04-02 3:14 ` Ming Qian(OSS)
2026-04-08 21:11 ` Nicolas Dufresne
0 siblings, 1 reply; 16+ messages in thread
From: Ming Qian(OSS) @ 2026-04-02 3:14 UTC (permalink / raw)
To: Nicolas Dufresne, Frank Li
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
Hi Nicolas,
On 4/1/2026 10:23 AM, Ming Qian(OSS) wrote:
> Hi Nicolas,
>
> On 3/31/2026 10:54 PM, Nicolas Dufresne wrote:
>> Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
>>> On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
>>>> From: Ming Qian <ming.qian@oss.nxp.com>
>>>>
>>>> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
>>>> applications to query the total amount of memory currently used
>>>> by a device instance.
>>>>
>>>> This control reports the memory consumption in bytes, including
>>>> internal buffers, intermediate processing data, and other
>>>> driver-managed allocations. Applications can use this information
>>>> for debugging, resource monitoring, or making informed decisions
>>>> about buffer allocation strategies.
>>>>
>>>> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
>>>> ---
>>>
>>> Not sure why not export these information by debugfs, or any benefit vs
>>> debugfs?
>>
>> There is also a on-going proposal that uses fdinfo.
>>
>> Nicolas
>>
>
> Thanks for the reminder about the ongoing fdinfo proposal.
>
> Just to confirm, you are referring to Detlev’s ongoing fdinfo proposal,
> specifically this series:
> https://lore.kernel.org/lkml/20260212162328.192217-1-
> detlev.casanova@collabora.com/
>
> I will align my work with it and switch to using fdinfo.
> Once the show_fdinfo support from that series is merged, I will prepare
> the next revision of my patch accordingly.
>
> Regards,
> Ming
>
Regarding the discussion about using fdinfo instead of a V4L2 control, I
have two questions:
1. Key consistency in fdinfo
fdinfo uses key–value pairs, which is flexible, but if multiple
drivers want to expose the same “memory usage” information,
they need to agree on a common key name and meaning. Otherwise
user‑space must handle each driver differently. A V4L2 control
naturally provides a unified interface without this coordination
effort.
2. Lack of notification in fdinfo
With a control, user‑space can subscribe to control events and
receive notifications when the memory usage changes. fdinfo does
not have a built‑in event mechanism, so users must either poll
or rely on additional eventfd‑like or custom event mechanisms.
Do you have any suggestions or existing practices to address these two
issues when using fdinfo?
Thanks again for your time and comments.
Regards,
Ming
>>>
>>> Generanlly document should be first patch, then driver change.
>>>
>>> Frank
>>>
>>>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
>>>> include/uapi/linux/v4l2-controls.h | 4 +++-
>>>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/
>>>> media/v4l2-core/v4l2-ctrls-defs.c
>>>> index 551426c4cd01..053db78ff661 100644
>>>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>>>> case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
>>>> case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
>>>> case V4L2_CID_COLORFX_RGB: return "Color Effects,
>>>> RGB";
>>>> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>>>>
>>>> /*
>>>> * Codec controls
>>>> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char
>>>> **name, enum v4l2_ctrl_type *type,
>>>> *min = 0;
>>>> *max = 0xffff;
>>>> break;
>>>> + case V4L2_CID_MEMORY_USAGE:
>>>> + *type = V4L2_CTRL_TYPE_INTEGER64;
>>>> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>>> + *min = 0;
>>>> + *max = S64_MAX;
>>>> + *step = 1;
>>>> + break;
>>>> case V4L2_CID_FLASH_FAULT:
>>>> case V4L2_CID_JPEG_ACTIVE_MARKER:
>>>> case V4L2_CID_3A_LOCK:
>>>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/
>>>> linux/v4l2-controls.h
>>>> index 68dd0c4e47b2..02c6f960d38e 100644
>>>> --- a/include/uapi/linux/v4l2-controls.h
>>>> +++ b/include/uapi/linux/v4l2-controls.h
>>>> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
>>>> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
>>>> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>>>>
>>>> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
>>>> +
>>>> /* last CID + 1 */
>>>> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
>>>> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>>>>
>>>> /* USER-class private control IDs */
>>>>
>>>> --
>>>> 2.53.0
>>>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-04-02 3:14 ` Ming Qian(OSS)
@ 2026-04-08 21:11 ` Nicolas Dufresne
2026-04-09 14:29 ` Detlev Casanova
0 siblings, 1 reply; 16+ messages in thread
From: Nicolas Dufresne @ 2026-04-08 21:11 UTC (permalink / raw)
To: Ming Qian(OSS), Frank Li, Detlev Casanova
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
[-- Attachment #1: Type: text/plain, Size: 5754 bytes --]
Le jeudi 02 avril 2026 à 11:14 +0800, Ming Qian(OSS) a écrit :
> Hi Nicolas,
>
> On 4/1/2026 10:23 AM, Ming Qian(OSS) wrote:
> > Hi Nicolas,
> >
> > On 3/31/2026 10:54 PM, Nicolas Dufresne wrote:
> > > Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
> > > > On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
> > > > > From: Ming Qian <ming.qian@oss.nxp.com>
> > > > >
> > > > > Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
> > > > > applications to query the total amount of memory currently used
> > > > > by a device instance.
> > > > >
> > > > > This control reports the memory consumption in bytes, including
> > > > > internal buffers, intermediate processing data, and other
> > > > > driver-managed allocations. Applications can use this information
> > > > > for debugging, resource monitoring, or making informed decisions
> > > > > about buffer allocation strategies.
> > > > >
> > > > > Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
> > > > > ---
> > > >
> > > > Not sure why not export these information by debugfs, or any benefit vs
> > > > debugfs?
> > >
> > > There is also a on-going proposal that uses fdinfo.
> > >
> > > Nicolas
> > >
> >
> > Thanks for the reminder about the ongoing fdinfo proposal.
> >
> > Just to confirm, you are referring to Detlev’s ongoing fdinfo proposal,
> > specifically this series:
> > https://lore.kernel.org/lkml/20260212162328.192217-1-
> > detlev.casanova@collabora.com/
> >
> > I will align my work with it and switch to using fdinfo.
> > Once the show_fdinfo support from that series is merged, I will prepare
> > the next revision of my patch accordingly.
> >
> > Regards,
> > Ming
> >
>
> Regarding the discussion about using fdinfo instead of a V4L2 control, I
> have two questions:
>
> 1. Key consistency in fdinfo
> fdinfo uses key–value pairs, which is flexible, but if multiple
> drivers want to expose the same “memory usage” information,
> they need to agree on a common key name and meaning. Otherwise
> user‑space must handle each driver differently. A V4L2 control
> naturally provides a unified interface without this coordination
> effort.
>
>
> 2. Lack of notification in fdinfo
> With a control, user‑space can subscribe to control events and
> receive notifications when the memory usage changes. fdinfo does
> not have a built‑in event mechanism, so users must either poll
> or rely on additional eventfd‑like or custom event mechanisms.
>
> Do you have any suggestions or existing practices to address these two
> issues when using fdinfo?
>
> Thanks again for your time and comments.
Added Detlev in CC. You can also refer to his work through:
https://lore.kernel.org/all/20260212162328.192217-1-detlev.casanova@collabora.com/
Nicolas
>
> Regards,
> Ming
>
> > > >
> > > > Generanlly document should be first patch, then driver change.
> > > >
> > > > Frank
> > > >
> > > > > drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
> > > > > include/uapi/linux/v4l2-controls.h | 4 +++-
> > > > > 2 files changed, 11 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/
> > > > > media/v4l2-core/v4l2-ctrls-defs.c
> > > > > index 551426c4cd01..053db78ff661 100644
> > > > > --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> > > > > +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
> > > > > @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
> > > > > case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
> > > > > case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
> > > > > case V4L2_CID_COLORFX_RGB: return "Color Effects,
> > > > > RGB";
> > > > > + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
> > > > >
> > > > > /*
> > > > > * Codec controls
> > > > > @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char
> > > > > **name, enum v4l2_ctrl_type *type,
> > > > > *min = 0;
> > > > > *max = 0xffff;
> > > > > break;
> > > > > + case V4L2_CID_MEMORY_USAGE:
> > > > > + *type = V4L2_CTRL_TYPE_INTEGER64;
> > > > > + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
> > > > > + *min = 0;
> > > > > + *max = S64_MAX;
> > > > > + *step = 1;
> > > > > + break;
> > > > > case V4L2_CID_FLASH_FAULT:
> > > > > case V4L2_CID_JPEG_ACTIVE_MARKER:
> > > > > case V4L2_CID_3A_LOCK:
> > > > > diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/
> > > > > linux/v4l2-controls.h
> > > > > index 68dd0c4e47b2..02c6f960d38e 100644
> > > > > --- a/include/uapi/linux/v4l2-controls.h
> > > > > +++ b/include/uapi/linux/v4l2-controls.h
> > > > > @@ -110,8 +110,10 @@ enum v4l2_colorfx {
> > > > > #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
> > > > > #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
> > > > >
> > > > > +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
> > > > > +
> > > > > /* last CID + 1 */
> > > > > -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
> > > > > +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
> > > > >
> > > > > /* USER-class private control IDs */
> > > > >
> > > > > --
> > > > > 2.53.0
> > > > >
> >
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-04-08 21:11 ` Nicolas Dufresne
@ 2026-04-09 14:29 ` Detlev Casanova
2026-04-10 2:53 ` Ming Qian(OSS)
0 siblings, 1 reply; 16+ messages in thread
From: Detlev Casanova @ 2026-04-09 14:29 UTC (permalink / raw)
To: Nicolas Dufresne, Ming Qian(OSS), Frank Li
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
On 4/8/26 17:11, Nicolas Dufresne wrote:
> Le jeudi 02 avril 2026 à 11:14 +0800, Ming Qian(OSS) a écrit :
>> Hi Nicolas,
>>
>> On 4/1/2026 10:23 AM, Ming Qian(OSS) wrote:
>>> Hi Nicolas,
>>>
>>> On 3/31/2026 10:54 PM, Nicolas Dufresne wrote:
>>>> Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
>>>>> On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
>>>>>> From: Ming Qian <ming.qian@oss.nxp.com>
>>>>>>
>>>>>> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
>>>>>> applications to query the total amount of memory currently used
>>>>>> by a device instance.
>>>>>>
>>>>>> This control reports the memory consumption in bytes, including
>>>>>> internal buffers, intermediate processing data, and other
>>>>>> driver-managed allocations. Applications can use this information
>>>>>> for debugging, resource monitoring, or making informed decisions
>>>>>> about buffer allocation strategies.
>>>>>>
>>>>>> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
>>>>>> ---
>>>>> Not sure why not export these information by debugfs, or any benefit vs
>>>>> debugfs?
>>>> There is also a on-going proposal that uses fdinfo.
>>>>
>>>> Nicolas
>>>>
>>> Thanks for the reminder about the ongoing fdinfo proposal.
>>>
>>> Just to confirm, you are referring to Detlev’s ongoing fdinfo proposal,
>>> specifically this series:
>>> https://lore.kernel.org/lkml/20260212162328.192217-1-
>>> detlev.casanova@collabora.com/
>>>
>>> I will align my work with it and switch to using fdinfo.
>>> Once the show_fdinfo support from that series is merged, I will prepare
>>> the next revision of my patch accordingly.
>>>
>>> Regards,
>>> Ming
>>>
>> Regarding the discussion about using fdinfo instead of a V4L2 control, I
>> have two questions:
>>
>> 1. Key consistency in fdinfo
>> fdinfo uses key–value pairs, which is flexible, but if multiple
>> drivers want to expose the same “memory usage” information,
>> they need to agree on a common key name and meaning. Otherwise
>> user‑space must handle each driver differently. A V4L2 control
>> naturally provides a unified interface without this coordination
>> effort.
>>
>>
>> 2. Lack of notification in fdinfo
>> With a control, user‑space can subscribe to control events and
>> receive notifications when the memory usage changes. fdinfo does
>> not have a built‑in event mechanism, so users must either poll
>> or rely on additional eventfd‑like or custom event mechanisms.
>>
>> Do you have any suggestions or existing practices to address these two
>> issues when using fdinfo?
>>
>> Thanks again for your time and comments.
> Added Detlev in CC. You can also refer to his work through:
>
> https://lore.kernel.org/all/20260212162328.192217-1-detlev.casanova@collabora.com/
>
> Nicolas
Hi Ming !
One of the reasons for using fdinfo is that it's already being used in
the drm subsystem and it is working well.
Of course, in DRM, drivers don't allocate a lot of memory themselves,
userspace drivers (in mesa) go through the DRM uAPI to allocate buffers,
making the DRM subsystem aware of all allocated memory.
That lets DRM show memory stats in a standard way for all drm drivers.
In v4l2, memory allocation is shared between userspace and the driver.
We could have drivers report memory usage through a callback and
v4l2-core can add the standard field based on that.
For notifications, I don't really see a need for that, most tracing
tools will use polling (I'm thinking perfetto, but also top-like tools).
We could have a max-mem-usage field if we'd want to make sure we don't
miss the maximum memory usage between 2 polls.
Finally, I think v4l2 controls should only be used to control, configure
and exchange data with video devices, not get stat information on what
the driver is doing.
Detlev.
>
>> Regards,
>> Ming
>>
>>>>> Generanlly document should be first patch, then driver change.
>>>>>
>>>>> Frank
>>>>>
>>>>>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
>>>>>> include/uapi/linux/v4l2-controls.h | 4 +++-
>>>>>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/
>>>>>> media/v4l2-core/v4l2-ctrls-defs.c
>>>>>> index 551426c4cd01..053db78ff661 100644
>>>>>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>>>> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>>>>>> case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
>>>>>> case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
>>>>>> case V4L2_CID_COLORFX_RGB: return "Color Effects,
>>>>>> RGB";
>>>>>> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>>>>>>
>>>>>> /*
>>>>>> * Codec controls
>>>>>> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char
>>>>>> **name, enum v4l2_ctrl_type *type,
>>>>>> *min = 0;
>>>>>> *max = 0xffff;
>>>>>> break;
>>>>>> + case V4L2_CID_MEMORY_USAGE:
>>>>>> + *type = V4L2_CTRL_TYPE_INTEGER64;
>>>>>> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>>>>> + *min = 0;
>>>>>> + *max = S64_MAX;
>>>>>> + *step = 1;
>>>>>> + break;
>>>>>> case V4L2_CID_FLASH_FAULT:
>>>>>> case V4L2_CID_JPEG_ACTIVE_MARKER:
>>>>>> case V4L2_CID_3A_LOCK:
>>>>>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/
>>>>>> linux/v4l2-controls.h
>>>>>> index 68dd0c4e47b2..02c6f960d38e 100644
>>>>>> --- a/include/uapi/linux/v4l2-controls.h
>>>>>> +++ b/include/uapi/linux/v4l2-controls.h
>>>>>> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
>>>>>> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
>>>>>> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>>>>>>
>>>>>> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
>>>>>> +
>>>>>> /* last CID + 1 */
>>>>>> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
>>>>>> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>>>>>>
>>>>>> /* USER-class private control IDs */
>>>>>>
>>>>>> --
>>>>>> 2.53.0
>>>>>>
^ permalink raw reply [flat|nested] 16+ messages in thread* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-04-09 14:29 ` Detlev Casanova
@ 2026-04-10 2:53 ` Ming Qian(OSS)
0 siblings, 0 replies; 16+ messages in thread
From: Ming Qian(OSS) @ 2026-04-10 2:53 UTC (permalink / raw)
To: Detlev Casanova, Nicolas Dufresne, Frank Li
Cc: linux-media, mchehab, hverkuil-cisco, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, xiahong.bao, eagle.zhou,
imx, linux-kernel, linux-arm-kernel
Hi Detlev,
On 4/9/2026 10:29 PM, Detlev Casanova wrote:
>
>
> On 4/8/26 17:11, Nicolas Dufresne wrote:
>> Le jeudi 02 avril 2026 à 11:14 +0800, Ming Qian(OSS) a écrit :
>>> Hi Nicolas,
>>>
>>> On 4/1/2026 10:23 AM, Ming Qian(OSS) wrote:
>>>> Hi Nicolas,
>>>>
>>>> On 3/31/2026 10:54 PM, Nicolas Dufresne wrote:
>>>>> Le mardi 31 mars 2026 à 10:33 -0400, Frank Li a écrit :
>>>>>> On Tue, Mar 31, 2026 at 03:23:11PM +0800,
>>>>>> ming.qian@oss.nxp.com wrote:
>>>>>>> From: Ming Qian <ming.qian@oss.nxp.com>
>>>>>>>
>>>>>>> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
>>>>>>> applications to query the total amount of memory currently used
>>>>>>> by a device instance.
>>>>>>>
>>>>>>> This control reports the memory consumption in bytes, including
>>>>>>> internal buffers, intermediate processing data, and other
>>>>>>> driver-managed allocations. Applications can use this information
>>>>>>> for debugging, resource monitoring, or making informed decisions
>>>>>>> about buffer allocation strategies.
>>>>>>>
>>>>>>> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
>>>>>>> ---
>>>>>> Not sure why not export these information by debugfs, or any
>>>>>> benefit vs
>>>>>> debugfs?
>>>>> There is also a on-going proposal that uses fdinfo.
>>>>>
>>>>> Nicolas
>>>>>
>>>> Thanks for the reminder about the ongoing fdinfo proposal.
>>>>
>>>> Just to confirm, you are referring to Detlev’s ongoing fdinfo proposal,
>>>> specifically this series:
>>>> https://lore.kernel.org/lkml/20260212162328.192217-1-
>>>> detlev.casanova@collabora.com/
>>>>
>>>> I will align my work with it and switch to using fdinfo.
>>>> Once the show_fdinfo support from that series is merged, I will prepare
>>>> the next revision of my patch accordingly.
>>>>
>>>> Regards,
>>>> Ming
>>>>
>>> Regarding the discussion about using fdinfo instead of a V4L2 control, I
>>> have two questions:
>>>
>>> 1. Key consistency in fdinfo
>>> fdinfo uses key–value pairs, which is flexible, but if multiple
>>> drivers want to expose the same “memory usage” information,
>>> they need to agree on a common key name and meaning. Otherwise
>>> user‑space must handle each driver differently. A V4L2 control
>>> naturally provides a unified interface without this coordination
>>> effort.
>>>
>>>
>>> 2. Lack of notification in fdinfo
>>> With a control, user‑space can subscribe to control events and
>>> receive notifications when the memory usage changes. fdinfo does
>>> not have a built‑in event mechanism, so users must either poll
>>> or rely on additional eventfd‑like or custom event mechanisms.
>>>
>>> Do you have any suggestions or existing practices to address these two
>>> issues when using fdinfo?
>>>
>>> Thanks again for your time and comments.
>> Added Detlev in CC. You can also refer to his work through:
>>
>> https://lore.kernel.org/all/20260212162328.192217-1-
>> detlev.casanova@collabora.com/
>>
>> Nicolas
> Hi Ming !
>
> One of the reasons for using fdinfo is that it's already being used in
> the drm subsystem and it is working well.
> Of course, in DRM, drivers don't allocate a lot of memory themselves,
> userspace drivers (in mesa) go through the DRM uAPI to allocate buffers,
> making the DRM subsystem aware of all allocated memory.
> That lets DRM show memory stats in a standard way for all drm drivers.
> In v4l2, memory allocation is shared between userspace and the driver.
> We could have drivers report memory usage through a callback and v4l2-
> core can add the standard field based on that.
>
> For notifications, I don't really see a need for that, most tracing
> tools will use polling (I'm thinking perfetto, but also top-like tools).
> We could have a max-mem-usage field if we'd want to make sure we don't
> miss the maximum memory usage between 2 polls.
>
> Finally, I think v4l2 controls should only be used to control, configure
> and exchange data with video devices, not get stat information on what
> the driver is doing.
>
> Detlev.
Thank you for your detailed explanation and suggestions.
Your points make sense, especially regarding fdinfo for standardized
stats reporting, polling being sufficient for tracing tools, and keeping
V4L2 controls focused on device control rather than driver statistics.
I'll revisit the design accordingly.
Regards,
Ming
>>
>>> Regards,
>>> Ming
>>>
>>>>>> Generanlly document should be first patch, then driver change.
>>>>>>
>>>>>> Frank
>>>>>>
>>>>>>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
>>>>>>> include/uapi/linux/v4l2-controls.h | 4 +++-
>>>>>>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>>>>>>
>>>>>>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/
>>>>>>> media/v4l2-core/v4l2-ctrls-defs.c
>>>>>>> index 551426c4cd01..053db78ff661 100644
>>>>>>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>>>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>>>>>>> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>>>>>>> case V4L2_CID_ALPHA_COMPONENT: return "Alpha
>>>>>>> Component";
>>>>>>> case V4L2_CID_COLORFX_CBCR: return "Color Effects,
>>>>>>> CbCr";
>>>>>>> case V4L2_CID_COLORFX_RGB: return "Color
>>>>>>> Effects,
>>>>>>> RGB";
>>>>>>> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>>>>>>>
>>>>>>> /*
>>>>>>> * Codec controls
>>>>>>> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char
>>>>>>> **name, enum v4l2_ctrl_type *type,
>>>>>>> *min = 0;
>>>>>>> *max = 0xffff;
>>>>>>> break;
>>>>>>> + case V4L2_CID_MEMORY_USAGE:
>>>>>>> + *type = V4L2_CTRL_TYPE_INTEGER64;
>>>>>>> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>>>>>>> + *min = 0;
>>>>>>> + *max = S64_MAX;
>>>>>>> + *step = 1;
>>>>>>> + break;
>>>>>>> case V4L2_CID_FLASH_FAULT:
>>>>>>> case V4L2_CID_JPEG_ACTIVE_MARKER:
>>>>>>> case V4L2_CID_3A_LOCK:
>>>>>>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/
>>>>>>> linux/v4l2-controls.h
>>>>>>> index 68dd0c4e47b2..02c6f960d38e 100644
>>>>>>> --- a/include/uapi/linux/v4l2-controls.h
>>>>>>> +++ b/include/uapi/linux/v4l2-controls.h
>>>>>>> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
>>>>>>> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
>>>>>>> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>>>>>>>
>>>>>>> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
>>>>>>> +
>>>>>>> /* last CID + 1 */
>>>>>>> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
>>>>>>> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>>>>>>>
>>>>>>> /* USER-class private control IDs */
>>>>>>>
>>>>>>> --
>>>>>>> 2.53.0
>>>>>>>
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 14:33 ` Frank Li
2026-03-31 14:54 ` Nicolas Dufresne
@ 2026-04-01 2:07 ` Ming Qian(OSS)
1 sibling, 0 replies; 16+ messages in thread
From: Ming Qian(OSS) @ 2026-04-01 2:07 UTC (permalink / raw)
To: Frank Li
Cc: linux-media, mchehab, hverkuil-cisco, nicolas, sebastian.fricke,
shawnguo, s.hauer, kernel, festevam, linux-imx, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
Hi Frank,
On 3/31/2026 10:33 PM, Frank Li wrote:
> On Tue, Mar 31, 2026 at 03:23:11PM +0800, ming.qian@oss.nxp.com wrote:
>> From: Ming Qian <ming.qian@oss.nxp.com>
>>
>> Add a new read-only control V4L2_CID_MEMORY_USAGE that allows
>> applications to query the total amount of memory currently used
>> by a device instance.
>>
>> This control reports the memory consumption in bytes, including
>> internal buffers, intermediate processing data, and other
>> driver-managed allocations. Applications can use this information
>> for debugging, resource monitoring, or making informed decisions
>> about buffer allocation strategies.
>>
>> Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
>> ---
>
> Not sure why not export these information by debugfs, or any benefit vs
> debugfs?
>
> Generanlly document should be first patch, then driver change.
>
> Frank
Thanks for the comments.
The key reason for adding a V4L2 ctrl is that the original requirement
(from Android) is to query the memory usage per VPU instance in a simple
and stable way. A ctrl naturally fits this use case, as userspace
already has the instance fd and does not need to locate or map any
external paths. In contrast, relying only on debugfs would require
userspace to figure out the relationship between an instance and a
debugfs node, which is neither stable nor friendly for production
systems where debugfs may not even be available.
Debugfs is added only to expose the full hierarchical memory‑tracking
structure (device → instance → queue) for debugging and analysis. It
complements the ctrl, but cannot replace it for the original functional
requirement.
I will reorder the documentation patch to come first in the next
revision.
Regards,
Ming
>
>> drivers/media/v4l2-core/v4l2-ctrls-defs.c | 8 ++++++++
>> include/uapi/linux/v4l2-controls.h | 4 +++-
>> 2 files changed, 11 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> index 551426c4cd01..053db78ff661 100644
>> --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c
>> @@ -831,6 +831,7 @@ const char *v4l2_ctrl_get_name(u32 id)
>> case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component";
>> case V4L2_CID_COLORFX_CBCR: return "Color Effects, CbCr";
>> case V4L2_CID_COLORFX_RGB: return "Color Effects, RGB";
>> + case V4L2_CID_MEMORY_USAGE: return "Memory Usage";
>>
>> /*
>> * Codec controls
>> @@ -1476,6 +1477,13 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>> *min = 0;
>> *max = 0xffff;
>> break;
>> + case V4L2_CID_MEMORY_USAGE:
>> + *type = V4L2_CTRL_TYPE_INTEGER64;
>> + *flags |= V4L2_CTRL_FLAG_READ_ONLY;
>> + *min = 0;
>> + *max = S64_MAX;
>> + *step = 1;
>> + break;
>> case V4L2_CID_FLASH_FAULT:
>> case V4L2_CID_JPEG_ACTIVE_MARKER:
>> case V4L2_CID_3A_LOCK:
>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
>> index 68dd0c4e47b2..02c6f960d38e 100644
>> --- a/include/uapi/linux/v4l2-controls.h
>> +++ b/include/uapi/linux/v4l2-controls.h
>> @@ -110,8 +110,10 @@ enum v4l2_colorfx {
>> #define V4L2_CID_COLORFX_CBCR (V4L2_CID_BASE+42)
>> #define V4L2_CID_COLORFX_RGB (V4L2_CID_BASE+43)
>>
>> +#define V4L2_CID_MEMORY_USAGE (V4L2_CID_BASE+44)
>> +
>> /* last CID + 1 */
>> -#define V4L2_CID_LASTP1 (V4L2_CID_BASE+44)
>> +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+45)
>>
>> /* USER-class private control IDs */
>>
>> --
>> 2.53.0
>>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [RFC PATCH 2/7] docs: media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
2026-03-31 7:23 ` [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 7:23 ` [RFC PATCH 3/7] media: v4l2-memtrack: Add V4L2 memory tracking infrastructure ming.qian
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add documentation for the V4L2_CID_MEMORY_USAGE control in the
userspace API documentation. This read-only control allows applications
to query the total amount of memory currently used by a device instance.
The documentation explains:
- The control reports memory usage in bytes for driver-managed allocations
- It includes internal buffers, intermediate processing data, and other
driver allocations associated with the instance
- Applications can use it for debugging, resource monitoring, and making
informed buffer allocation decisions
- The value may change dynamically during device operation
- It only reports driver-managed memory, not application-allocated buffers
Update V4L2_CID_LASTP1 definition to reflect the new control as the
last predefined control ID.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
.../userspace-api/media/v4l/control.rst | 22 ++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/Documentation/userspace-api/media/v4l/control.rst b/Documentation/userspace-api/media/v4l/control.rst
index 19372bb32c4b..6904c5bdbf37 100644
--- a/Documentation/userspace-api/media/v4l/control.rst
+++ b/Documentation/userspace-api/media/v4l/control.rst
@@ -316,9 +316,29 @@ Control IDs
set the alpha component value of all pixels for further processing
in the device.
+``V4L2_CID_MEMORY_USAGE`` ``(integer64)``
+ This is an optional read-only control that reports the total amount of
+ memory, in bytes, currently allocated and used by this device instance.
+ This includes memory used for internal buffers, intermediate processing
+ data, and any other driver-managed allocations associated with the
+ instance.
+
+ Applications can use this control to monitor memory consumption for
+ debugging purposes, resource management, or to make informed decisions
+ about buffer allocation strategies. The value may change dynamically
+ as the device operates, for example when buffers are allocated or
+ released during streaming.
+
+ Note that this control only reports memory managed by the driver for
+ this specific instance; it does not include memory allocated by the
+ application itself (e.g., userspace buffers passed to the driver).
+
+ Not all drivers support this control. Applications should query for
+ its availability before use.
+
``V4L2_CID_LASTP1``
End of the predefined control IDs (currently
- ``V4L2_CID_ALPHA_COMPONENT`` + 1).
+ ``V4L2_CID_MEMORY_USAGE`` + 1).
``V4L2_CID_PRIVATE_BASE``
ID of the first custom (driver specific) control. Applications
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* [RFC PATCH 3/7] media: v4l2-memtrack: Add V4L2 memory tracking infrastructure
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
2026-03-31 7:23 ` [RFC PATCH 1/7] media: v4l2-ctrls: Add V4L2_CID_MEMORY_USAGE control ming.qian
2026-03-31 7:23 ` [RFC PATCH 2/7] docs: " ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 7:23 ` [RFC PATCH 4/7] docs: media: v4l2-memtrack: Add driver API documentation ming.qian
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add a hierarchical memory tracking system for V4L2 devices that allows
drivers to monitor and report memory usage. This infrastructure provides:
- Tree-structured memory tracking with parent-child relationships
- Per-node memory accounting with allocation counts
- Automatic aggregation of memory usage up the hierarchy
- debugfs interface for inspecting memory usage trees
- Notification callbacks for memory usage changes
The tracking system uses a context-based design where each root node
creates its own tracking tree. Memory changes propagate notifications up
the tree, allowing drivers to update controls or take other actions.
The debugfs interface creates entries under <debugfs>/v4l2-memtrack/
showing hierarchical memory usage with indentation, allocation counts,
and process information.
Drivers can use this to track internal buffers, intermediate processing
data, and other allocations, providing visibility into memory consumption
for debugging and resource monitoring.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
drivers/media/common/Kconfig | 1 +
drivers/media/common/Makefile | 2 +-
drivers/media/common/v4l2-memtrack/Kconfig | 19 +
drivers/media/common/v4l2-memtrack/Makefile | 3 +
.../common/v4l2-memtrack/v4l2-memtrack.c | 825 ++++++++++++++++++
include/media/v4l2-memtrack.h | 220 +++++
6 files changed, 1069 insertions(+), 1 deletion(-)
create mode 100644 drivers/media/common/v4l2-memtrack/Kconfig
create mode 100644 drivers/media/common/v4l2-memtrack/Makefile
create mode 100644 drivers/media/common/v4l2-memtrack/v4l2-memtrack.c
create mode 100644 include/media/v4l2-memtrack.h
diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig
index adcb6655385a..4da632f53970 100644
--- a/drivers/media/common/Kconfig
+++ b/drivers/media/common/Kconfig
@@ -27,5 +27,6 @@ config VIDEO_TVEEPROM
source "drivers/media/common/b2c2/Kconfig"
source "drivers/media/common/saa7146/Kconfig"
source "drivers/media/common/siano/Kconfig"
+source "drivers/media/common/v4l2-memtrack/Kconfig"
source "drivers/media/common/v4l2-tpg/Kconfig"
source "drivers/media/common/videobuf2/Kconfig"
diff --git a/drivers/media/common/Makefile b/drivers/media/common/Makefile
index c5ab905e7c20..0010a4d904ca 100644
--- a/drivers/media/common/Makefile
+++ b/drivers/media/common/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += b2c2/ saa7146/ siano/ v4l2-tpg/ videobuf2/
+obj-y += b2c2/ saa7146/ siano/ v4l2-memtrack/ v4l2-tpg/ videobuf2/
# Please keep it alphabetically sorted by Kconfig name
# (e. g. LC_ALL=C sort Makefile)
diff --git a/drivers/media/common/v4l2-memtrack/Kconfig b/drivers/media/common/v4l2-memtrack/Kconfig
new file mode 100644
index 000000000000..f4c97117b779
--- /dev/null
+++ b/drivers/media/common/v4l2-memtrack/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config V4L2_MEMTRACK
+ tristate "V4L2 memory usage tracking support"
+ help
+ This option enables hierarchical memory allocation tracking
+ for V4L2 devices. It provides:
+
+ - Tree-structured memory usage monitoring
+ - Per-device and per-context tracking
+ - debugfs interface at /sys/kernel/debug/v4l2-memtrack/
+ - Optional V4L2 control for userspace queries
+
+ This is useful for debugging memory leaks and monitoring
+ buffer allocation in video drivers.
+
+ To compile this as a module, choose M here.
+
+ If unsure, say N.
diff --git a/drivers/media/common/v4l2-memtrack/Makefile b/drivers/media/common/v4l2-memtrack/Makefile
new file mode 100644
index 000000000000..5ed59453b35a
--- /dev/null
+++ b/drivers/media/common/v4l2-memtrack/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_V4L2_MEMTRACK) += v4l2-memtrack.o
diff --git a/drivers/media/common/v4l2-memtrack/v4l2-memtrack.c b/drivers/media/common/v4l2-memtrack/v4l2-memtrack.c
new file mode 100644
index 000000000000..96eeaef7a653
--- /dev/null
+++ b/drivers/media/common/v4l2-memtrack/v4l2-memtrack.c
@@ -0,0 +1,825 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * V4L2 Memory Usage Tracker
+ *
+ * Copyright 2026 NXP
+ *
+ * Provides hierarchical memory allocation tracking for V4L2 devices.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/atomic.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/workqueue.h>
+
+#include <media/v4l2-memtrack.h>
+
+#define V4L2_MEMTRACK_DEBUGFS_ROOT "v4l2-memtrack"
+#define V4L2_MEMTRACK_MAX_DEPTH 16
+
+/**
+ * struct v4l2_memtrack_ctx - Memory tracker context
+ * @name: Tracker name (shown in debugfs)
+ * @root: Root node of tracking hierarchy
+ * @debugfs: debugfs file entry
+ * @lock: Protects the node tree
+ */
+struct v4l2_memtrack_ctx {
+ const char *name;
+ struct v4l2_memtrack_node *root;
+ struct dentry *debugfs;
+ struct mutex lock;
+};
+
+/**
+ * struct v4l2_memtrack_node - Memory tracking node
+ * @list: Linkage in parent's children list
+ * @parent: Parent node
+ * @children: List of child nodes
+ * @bytes: Memory usage in bytes
+ * @alloc_count: Number of allocations
+ * @name: Node name
+ * @depth: Depth of this node in the tree (root = 0)
+ * @pid: Process ID that created this node
+ * @tgid: Thread group ID that created this node
+ * @ctx: Back pointer to context
+ * @is_leaf: True if this is a leaf node (internal use only)
+ * @notify: Notification callback for memory changes
+ * @notify_priv: Private data for notification callback
+ * @notify_work: Per-node delayed work for coalesced notifications
+ * @notify_delay_ms: Notification delay (<0: off, 0: immediate, >0: delayed)
+ * @in_notify: Flag indicating if callback is currently executing
+ * @notify_done: Completion for waiting on callback completion
+ */
+struct v4l2_memtrack_node {
+ struct list_head list;
+ struct v4l2_memtrack_node *parent;
+ struct list_head children;
+
+ size_t bytes;
+ unsigned int alloc_count;
+
+ const char *name;
+ unsigned int depth;
+ pid_t pid;
+ pid_t tgid;
+
+ struct v4l2_memtrack_ctx *ctx;
+ bool is_leaf;
+
+ /* Notify fields - only used by non-leaf nodes */
+ v4l2_memtrack_notify_fn notify;
+ void *notify_priv;
+ struct delayed_work notify_work;
+ int notify_delay_ms;
+ bool in_notify;
+ struct completion notify_done;
+};
+
+static struct dentry *v4l2_memtrack_debugfs_root;
+static DEFINE_MUTEX(v4l2_memtrack_debugfs_lock);
+static struct kref v4l2_memtrack_debugfs_kref;
+static bool v4l2_memtrack_debugfs_initialized;
+
+struct v4l2_memtrack_iter_state {
+ struct v4l2_memtrack_node *node;
+ struct list_head *next_child;
+};
+
+typedef int (*v4l2_memtrack_visit_fn)(struct v4l2_memtrack_node *node, void *data);
+
+static int v4l2_memtrack_for_each_locked(struct v4l2_memtrack_node *root,
+ v4l2_memtrack_visit_fn visit,
+ void *data)
+{
+ struct v4l2_memtrack_iter_state stack[V4L2_MEMTRACK_MAX_DEPTH];
+ struct v4l2_memtrack_node *node;
+ int sp = 0;
+ int ret;
+
+ lockdep_assert_held(&root->ctx->lock);
+
+ ret = visit(root, data);
+ if (ret)
+ return ret;
+
+ if (list_empty(&root->children))
+ return 0;
+
+ stack[sp].node = root;
+ stack[sp].next_child = root->children.next;
+ sp++;
+
+ while (sp > 0) {
+ struct v4l2_memtrack_iter_state *top = &stack[sp - 1];
+
+ if (top->next_child == &top->node->children) {
+ sp--;
+ continue;
+ }
+
+ node = list_entry(top->next_child,
+ struct v4l2_memtrack_node, list);
+ top->next_child = top->next_child->next;
+
+ ret = visit(node, data);
+ if (ret)
+ return ret;
+
+ if (!list_empty(&node->children) &&
+ sp < V4L2_MEMTRACK_MAX_DEPTH) {
+ stack[sp].node = node;
+ stack[sp].next_child = node->children.next;
+ sp++;
+ }
+ }
+
+ return 0;
+}
+
+static void v4l2_memtrack_debugfs_release(struct kref *kref)
+{
+ debugfs_remove(v4l2_memtrack_debugfs_root);
+ v4l2_memtrack_debugfs_root = NULL;
+ v4l2_memtrack_debugfs_initialized = false;
+}
+
+static void v4l2_memtrack_debugfs_get(void)
+{
+ guard(mutex)(&v4l2_memtrack_debugfs_lock);
+
+ if (!v4l2_memtrack_debugfs_initialized) {
+ kref_init(&v4l2_memtrack_debugfs_kref);
+ v4l2_memtrack_debugfs_root =
+ debugfs_create_dir(V4L2_MEMTRACK_DEBUGFS_ROOT, NULL);
+ v4l2_memtrack_debugfs_initialized = true;
+ } else {
+ kref_get(&v4l2_memtrack_debugfs_kref);
+ }
+}
+
+static void v4l2_memtrack_debugfs_put(void)
+{
+ guard(mutex)(&v4l2_memtrack_debugfs_lock);
+ kref_put(&v4l2_memtrack_debugfs_kref, v4l2_memtrack_debugfs_release);
+}
+
+static void v4l2_memtrack_notify_work_handler(struct work_struct *work);
+
+static int v4l2_memtrack_node_init(struct v4l2_memtrack_node *node,
+ struct v4l2_memtrack_ctx *ctx,
+ unsigned int depth,
+ const char *name,
+ bool is_leaf)
+{
+ INIT_LIST_HEAD(&node->list);
+ INIT_LIST_HEAD(&node->children);
+ node->bytes = 0;
+ node->alloc_count = 0;
+ node->ctx = ctx;
+ node->depth = depth;
+ node->tgid = current->tgid;
+ node->pid = current->pid;
+ node->is_leaf = is_leaf;
+
+ /* Initialize notify fields only for non-leaf nodes */
+ if (!is_leaf) {
+ node->notify = NULL;
+ node->notify_priv = NULL;
+ INIT_DELAYED_WORK(&node->notify_work,
+ v4l2_memtrack_notify_work_handler);
+ node->notify_delay_ms = 0;
+ node->in_notify = false;
+ init_completion(&node->notify_done);
+ }
+
+ if (name) {
+ node->name = kstrdup_const(name, GFP_KERNEL);
+ if (!node->name)
+ return -ENOMEM;
+ } else {
+ node->name = NULL;
+ }
+
+ return 0;
+}
+
+static inline const char *v4l2_memtrack_name(struct v4l2_memtrack_node *node)
+{
+ return node->name ? : "(unnamed)";
+}
+
+static int v4l2_memtrack_sum_visitor(struct v4l2_memtrack_node *node, void *data)
+{
+ size_t *total = data;
+
+ *total += node->bytes;
+ return 0;
+}
+
+static size_t v4l2_memtrack_sum_bytes_locked(struct v4l2_memtrack_node *root)
+{
+ size_t total = 0;
+
+ lockdep_assert_held(&root->ctx->lock);
+
+ v4l2_memtrack_for_each_locked(root, v4l2_memtrack_sum_visitor, &total);
+ return total;
+}
+
+static void v4l2_memtrack_do_notify_locked(struct v4l2_memtrack_node *node)
+{
+ size_t total;
+ v4l2_memtrack_notify_fn notify;
+ void *priv;
+ struct v4l2_memtrack_ctx *ctx = node->ctx;
+
+ lockdep_assert_held(&ctx->lock);
+
+ if (!node->notify)
+ return;
+
+ total = v4l2_memtrack_sum_bytes_locked(node);
+ notify = node->notify;
+ priv = node->notify_priv;
+
+ node->in_notify = true;
+ reinit_completion(&node->notify_done);
+
+ mutex_unlock(&ctx->lock);
+ notify(node, total, priv);
+ mutex_lock(&ctx->lock);
+
+ node->in_notify = false;
+ complete_all(&node->notify_done);
+}
+
+static void v4l2_memtrack_notify_work_handler(struct work_struct *work)
+{
+ struct v4l2_memtrack_node *node =
+ container_of(to_delayed_work(work),
+ struct v4l2_memtrack_node, notify_work);
+ struct v4l2_memtrack_ctx *ctx = node->ctx;
+
+ guard(mutex)(&ctx->lock);
+ v4l2_memtrack_do_notify_locked(node);
+}
+
+static void v4l2_memtrack_schedule_notify(struct v4l2_memtrack_node *node)
+{
+ int delay;
+
+ if (node->is_leaf || !node->notify)
+ return;
+
+ delay = node->notify_delay_ms;
+ if (delay < 0)
+ return;
+
+ if (delay == 0)
+ v4l2_memtrack_do_notify_locked(node);
+ else
+ schedule_delayed_work(&node->notify_work,
+ msecs_to_jiffies(delay));
+}
+
+static void v4l2_memtrack_notify_change_locked(struct v4l2_memtrack_node *node)
+{
+ struct v4l2_memtrack_node *cur;
+
+ lockdep_assert_held(&node->ctx->lock);
+
+ for (cur = node; cur; cur = cur->parent) {
+ if (!cur->is_leaf)
+ v4l2_memtrack_schedule_notify(cur);
+ }
+}
+
+static void v4l2_memtrack_do_notify(struct v4l2_memtrack_node *node)
+{
+ if (!node || !node->ctx)
+ return;
+
+ guard(mutex)(&node->ctx->lock);
+ v4l2_memtrack_notify_change_locked(node);
+}
+
+struct v4l2_memtrack_seq_ctx {
+ struct seq_file *seq;
+};
+
+static int v4l2_memtrack_seq_visitor(struct v4l2_memtrack_node *node, void *data)
+{
+ struct v4l2_memtrack_seq_ctx *ctx = data;
+ struct seq_file *s = ctx->seq;
+ size_t bytes;
+
+ bytes = v4l2_memtrack_sum_bytes_locked(node);
+
+ seq_printf(s, "%*s", node->depth * 2, "");
+
+ if (node->name)
+ seq_printf(s, "%s ", node->name);
+
+ if (node->is_leaf)
+ seq_puts(s, "[leaf] ");
+
+ if (node->tgid && node->pid)
+ seq_printf(s, "(tgid=%d, pid=%d) ", node->tgid, node->pid);
+
+ seq_printf(s, "usage: %zu", bytes);
+
+ if (node->alloc_count > 1 || (node->alloc_count == 1 && !list_empty(&node->children))) {
+ seq_printf(s, " (count=%u", node->alloc_count);
+ if (!list_empty(&node->children))
+ seq_printf(s, ", self=%zu", node->bytes);
+ seq_puts(s, ")");
+ }
+
+ seq_puts(s, "\n");
+ return 0;
+}
+
+static int v4l2_memtrack_seq_show(struct seq_file *s, void *data)
+{
+ struct v4l2_memtrack_ctx *ctx = s->private;
+ struct v4l2_memtrack_seq_ctx seq_ctx = { .seq = s };
+
+ guard(mutex)(&ctx->lock);
+
+ seq_printf(s, "Total memory usage: %zu bytes\n",
+ v4l2_memtrack_sum_bytes_locked(ctx->root));
+ v4l2_memtrack_for_each_locked(ctx->root, v4l2_memtrack_seq_visitor, &seq_ctx);
+
+ return 0;
+}
+
+static int v4l2_memtrack_debugfs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, v4l2_memtrack_seq_show, inode->i_private);
+}
+
+static const struct file_operations v4l2_memtrack_debugfs_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_memtrack_debugfs_open,
+ .release = single_release,
+ .read = seq_read,
+ .llseek = seq_lseek,
+};
+
+static void v4l2_memtrack_create_debugfs(struct v4l2_memtrack_ctx *ctx)
+{
+ guard(mutex)(&v4l2_memtrack_debugfs_lock);
+
+ if (IS_ERR_OR_NULL(v4l2_memtrack_debugfs_root))
+ return;
+
+ ctx->debugfs = debugfs_create_file(ctx->name, 0444,
+ v4l2_memtrack_debugfs_root,
+ ctx, &v4l2_memtrack_debugfs_fops);
+}
+
+static struct v4l2_memtrack_ctx *v4l2_memtrack_ctx_create(const char *name)
+{
+ struct v4l2_memtrack_ctx *ctx;
+
+ ctx = kzalloc_obj(*ctx);
+ if (!ctx)
+ return NULL;
+
+ if (name) {
+ ctx->name = kstrdup_const(name, GFP_KERNEL);
+ if (!ctx->name) {
+ kfree(ctx);
+ return NULL;
+ }
+ }
+
+ mutex_init(&ctx->lock);
+
+ return ctx;
+}
+
+static void v4l2_memtrack_ctx_destroy(struct v4l2_memtrack_ctx *ctx)
+{
+ debugfs_remove(ctx->debugfs);
+ mutex_destroy(&ctx->lock);
+ kfree_const(ctx->name);
+ kfree(ctx);
+ v4l2_memtrack_debugfs_put();
+}
+
+struct v4l2_memtrack_node *v4l2_memtrack_create_root(const char *name)
+{
+ struct v4l2_memtrack_ctx *ctx;
+ struct v4l2_memtrack_node *node;
+
+ v4l2_memtrack_debugfs_get();
+
+ ctx = v4l2_memtrack_ctx_create(name);
+ if (!ctx) {
+ v4l2_memtrack_debugfs_put();
+ return NULL;
+ }
+
+ node = kzalloc_obj(*node);
+ if (!node) {
+ v4l2_memtrack_ctx_destroy(ctx);
+ return NULL;
+ }
+
+ if (v4l2_memtrack_node_init(node, ctx, 0, name, false)) {
+ kfree(node);
+ v4l2_memtrack_ctx_destroy(ctx);
+ return NULL;
+ }
+
+ ctx->root = node;
+
+ if (name)
+ v4l2_memtrack_create_debugfs(ctx);
+
+ return node;
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_create_root);
+
+struct v4l2_memtrack_node *v4l2_memtrack_create_node(struct v4l2_memtrack_node *parent,
+ const char *name)
+{
+ struct v4l2_memtrack_ctx *ctx;
+ struct v4l2_memtrack_node *node;
+ unsigned int new_depth;
+
+ if (!parent || !parent->ctx)
+ return NULL;
+
+ /* Leaf nodes cannot have children */
+ if (parent->is_leaf) {
+ pr_warn_once("v4l2-memtrack: cannot create child under leaf node\n");
+ return NULL;
+ }
+
+ new_depth = parent->depth + 1;
+ if (new_depth >= V4L2_MEMTRACK_MAX_DEPTH) {
+ pr_warn_once("v4l2-memtrack: max depth %d reached, cannot create child node\n",
+ V4L2_MEMTRACK_MAX_DEPTH);
+ return NULL;
+ }
+
+ ctx = parent->ctx;
+
+ node = kzalloc_obj(*node);
+ if (!node)
+ return NULL;
+
+ if (v4l2_memtrack_node_init(node, ctx, new_depth, name, false)) {
+ kfree(node);
+ return NULL;
+ }
+
+ node->parent = parent;
+
+ scoped_guard(mutex, &ctx->lock)
+ list_add_tail(&node->list, &parent->children);
+
+ return node;
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_create_node);
+
+static void v4l2_memtrack_cancel_notify(struct v4l2_memtrack_node *node)
+{
+ bool wait_needed = false;
+
+ if (node->is_leaf)
+ return;
+
+ cancel_delayed_work_sync(&node->notify_work);
+
+ scoped_guard(mutex, &node->ctx->lock) {
+ node->notify = NULL;
+ node->notify_priv = NULL;
+ wait_needed = node->in_notify;
+ }
+
+ if (wait_needed)
+ wait_for_completion(&node->notify_done);
+}
+
+static void v4l2_memtrack_delete_subtree_locked(struct v4l2_memtrack_node *root)
+{
+ struct v4l2_memtrack_ctx *ctx = root->ctx;
+ struct v4l2_memtrack_node * const stop = root->parent;
+ struct v4l2_memtrack_node *node, *parent;
+
+ lockdep_assert_held(&ctx->lock);
+
+ node = root;
+ while (node) {
+ if (!list_empty(&node->children)) {
+ node = list_first_entry(&node->children,
+ struct v4l2_memtrack_node, list);
+ } else {
+ parent = node->parent;
+ list_del(&node->list);
+ kfree_const(node->name);
+ kfree(node);
+
+ if (parent == stop)
+ break;
+ node = parent;
+ }
+ }
+}
+
+static int v4l2_memtrack_find_notify_visitor(struct v4l2_memtrack_node *node,
+ void *data)
+{
+ struct v4l2_memtrack_node **found = data;
+
+ if (!node->is_leaf && node->notify) {
+ *found = node;
+ return 1; /* Stop iteration */
+ }
+ return 0;
+}
+
+static struct v4l2_memtrack_node *
+v4l2_memtrack_get_next_notify_node_locked(struct v4l2_memtrack_node *root)
+{
+ struct v4l2_memtrack_node *found = NULL;
+
+ lockdep_assert_held(&root->ctx->lock);
+
+ v4l2_memtrack_for_each_locked(root, v4l2_memtrack_find_notify_visitor,
+ &found);
+ return found;
+}
+
+void v4l2_memtrack_destroy_node(struct v4l2_memtrack_node *node)
+{
+ struct v4l2_memtrack_ctx *ctx;
+ struct v4l2_memtrack_node *parent;
+ struct v4l2_memtrack_node *notify_node;
+ bool is_root;
+
+ if (!node || !node->ctx)
+ return;
+
+ ctx = node->ctx;
+ parent = node->parent;
+ is_root = !parent;
+
+ if (v4l2_memtrack_read(node))
+ v4l2_memtrack_print_debug(node);
+
+ /*
+ * Cancel all notify callbacks in the subtree.
+ * Get one node with notify at a time while holding lock,
+ * then cancel it without lock to avoid deadlock.
+ */
+ if (!node->is_leaf) {
+ while (true) {
+ scoped_guard(mutex, &ctx->lock)
+ notify_node = v4l2_memtrack_get_next_notify_node_locked(node);
+
+ if (!notify_node)
+ break;
+
+ v4l2_memtrack_cancel_notify(notify_node);
+ }
+ }
+
+ scoped_guard(mutex, &ctx->lock)
+ v4l2_memtrack_delete_subtree_locked(node);
+
+ if (is_root)
+ v4l2_memtrack_ctx_destroy(ctx);
+ else
+ v4l2_memtrack_do_notify(parent);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_destroy_node);
+
+static int v4l2_memtrack_create_leaf_locked(struct v4l2_memtrack_node *node,
+ size_t bytes, const char *name)
+{
+ struct v4l2_memtrack_ctx *ctx = node->ctx;
+ struct v4l2_memtrack_node *child;
+ unsigned int new_depth;
+
+ lockdep_assert_held(&ctx->lock);
+
+ new_depth = node->depth + 1;
+ if (new_depth >= V4L2_MEMTRACK_MAX_DEPTH) {
+ pr_warn_once("v4l2-memtrack: max depth %d reached\n",
+ V4L2_MEMTRACK_MAX_DEPTH);
+ return -ENOSPC;
+ }
+
+ child = kzalloc(sizeof(*child), GFP_KERNEL);
+ if (!child)
+ return -ENOMEM;
+
+ if (v4l2_memtrack_node_init(child, ctx, new_depth, name, true)) {
+ kfree(child);
+ return -ENOMEM;
+ }
+
+ child->parent = node;
+ child->bytes = bytes;
+ child->alloc_count = 1;
+
+ list_add_tail(&child->list, &node->children);
+
+ return 0;
+}
+
+void v4l2_memtrack_add(struct v4l2_memtrack_node *node, size_t bytes,
+ const char *name)
+{
+ if (!node || !node->ctx)
+ return;
+
+ /* Leaf nodes cannot have children */
+ if (node->is_leaf) {
+ pr_warn_once("v4l2-memtrack: cannot add to leaf node\n");
+ return;
+ }
+
+ guard(mutex)(&node->ctx->lock);
+
+ if (name) {
+ /* Create a leaf node for named allocations */
+ if (v4l2_memtrack_create_leaf_locked(node, bytes, name) < 0) {
+ /* Fallback to direct tracking on failure */
+ node->bytes += bytes;
+ node->alloc_count++;
+ }
+ } else {
+ /* Direct tracking for unnamed allocations */
+ node->bytes += bytes;
+ node->alloc_count++;
+ }
+
+ v4l2_memtrack_notify_change_locked(node);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_add);
+
+void v4l2_memtrack_sub(struct v4l2_memtrack_node *node, size_t bytes,
+ const char *name)
+{
+ struct v4l2_memtrack_node *child;
+ struct v4l2_memtrack_node *found = NULL;
+
+ if (!node || !node->ctx)
+ return;
+
+ guard(mutex)(&node->ctx->lock);
+
+ /* Try to find and remove a matching leaf node if name is provided */
+ if (name && !node->is_leaf) {
+ list_for_each_entry(child, &node->children, list) {
+ if (!child->is_leaf)
+ continue;
+ if (child->bytes != bytes)
+ continue;
+ if (!child->name || strcmp(child->name, name))
+ continue;
+
+ list_del(&child->list);
+ found = child;
+ break;
+ }
+ }
+
+ if (found) {
+ kfree_const(found->name);
+ kfree(found);
+ } else {
+ /* Direct subtraction */
+ if (node->bytes < bytes) {
+ pr_warn_once("v4l2-memtrack: %s: bytes underflow\n",
+ v4l2_memtrack_name(node));
+ node->bytes = 0;
+ } else {
+ node->bytes -= bytes;
+ }
+
+ if (node->alloc_count > 0)
+ node->alloc_count--;
+ }
+
+ v4l2_memtrack_notify_change_locked(node);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_sub);
+
+void v4l2_memtrack_set(struct v4l2_memtrack_node *node, size_t bytes)
+{
+ if (!node || !node->ctx)
+ return;
+
+ guard(mutex)(&node->ctx->lock);
+
+ node->bytes = bytes;
+ node->alloc_count = bytes ? 1 : 0;
+ v4l2_memtrack_notify_change_locked(node);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_set);
+
+size_t v4l2_memtrack_read(struct v4l2_memtrack_node *node)
+{
+ struct v4l2_memtrack_ctx *ctx;
+ size_t total;
+
+ if (!node || !node->ctx)
+ return 0;
+
+ ctx = node->ctx;
+
+ scoped_guard(mutex, &ctx->lock)
+ total = v4l2_memtrack_sum_bytes_locked(node);
+
+ return total;
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_read);
+
+int v4l2_memtrack_register_notify(struct v4l2_memtrack_node *node,
+ v4l2_memtrack_notify_fn notify,
+ void *priv)
+{
+ if (!node || !node->ctx)
+ return -EINVAL;
+
+ /* Leaf nodes do not support notifications */
+ if (node->is_leaf)
+ return -EINVAL;
+
+ guard(mutex)(&node->ctx->lock);
+
+ if (node->notify)
+ return -EBUSY;
+
+ node->notify = notify;
+ node->notify_priv = priv;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_register_notify);
+
+void v4l2_memtrack_unregister_notify(struct v4l2_memtrack_node *node)
+{
+ if (!node || !node->ctx || node->is_leaf)
+ return;
+
+ v4l2_memtrack_cancel_notify(node);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_unregister_notify);
+
+void v4l2_memtrack_set_notify_delay(struct v4l2_memtrack_node *node, int delay_ms)
+{
+ if (!node || !node->ctx || node->is_leaf)
+ return;
+
+ guard(mutex)(&node->ctx->lock);
+ node->notify_delay_ms = delay_ms;
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_set_notify_delay);
+
+static int v4l2_memtrack_print_visitor(struct v4l2_memtrack_node *node, void *data)
+{
+ pr_debug("v4l2-memtrack: %*s%s%s: usage=%zu bytes, count=%u\n",
+ node->depth * 2, "",
+ v4l2_memtrack_name(node),
+ node->is_leaf ? " [leaf]" : "",
+ v4l2_memtrack_sum_bytes_locked(node),
+ node->alloc_count);
+ return 0;
+}
+
+void v4l2_memtrack_print_debug(struct v4l2_memtrack_node *node)
+{
+ struct v4l2_memtrack_ctx *ctx;
+
+ if (!node || !node->ctx)
+ return;
+
+ ctx = node->ctx;
+
+ pr_debug("v4l2-memtrack: Memory Tracker: %s\n", ctx->name ? : "(unnamed)");
+
+ scoped_guard(mutex, &ctx->lock)
+ v4l2_memtrack_for_each_locked(node, v4l2_memtrack_print_visitor, NULL);
+}
+EXPORT_SYMBOL_GPL(v4l2_memtrack_print_debug);
+
+MODULE_DESCRIPTION("V4L2 Memory Usage Tracker");
+MODULE_AUTHOR("Ming Qian <ming.qian@oss.nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/media/v4l2-memtrack.h b/include/media/v4l2-memtrack.h
new file mode 100644
index 000000000000..b146277ab98f
--- /dev/null
+++ b/include/media/v4l2-memtrack.h
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * V4L2 Memory Usage Tracker
+ *
+ * Copyright 2026 NXP
+ *
+ * Provides hierarchical memory allocation tracking for V4L2 devices,
+ * useful for debugging memory leaks and monitoring buffer usage.
+ */
+
+#ifndef _V4L2_MEMTRACK_H
+#define _V4L2_MEMTRACK_H
+
+#include <linux/types.h>
+
+struct v4l2_memtrack_node;
+
+/**
+ * typedef v4l2_memtrack_notify_fn - Memory change notification callback
+ * @node: The node whose subtree memory usage changed
+ * @total: Total memory usage of the node's subtree in bytes
+ * @priv: Private data passed during registration
+ *
+ * This callback is invoked when memory usage changes in the node or any
+ * of its descendants. The callback is executed without holding internal
+ * locks, so it may call most kernel functions safely.
+ *
+ * However, the callback MUST NOT call v4l2_memtrack_unregister_notify()
+ * or v4l2_memtrack_destroy_node() on the same node, as this will cause
+ * a deadlock. The callback should be kept reasonably short to avoid
+ * delaying other pending notifications.
+ */
+typedef void (*v4l2_memtrack_notify_fn)(struct v4l2_memtrack_node *node, size_t total, void *priv);
+
+#if IS_REACHABLE(CONFIG_V4L2_MEMTRACK)
+
+/**
+ * v4l2_memtrack_create_root - Create a root tracking node
+ * @name: Name for this tracker (shows in debugfs)
+ *
+ * Creates a root node that serves as the top of a tracking hierarchy.
+ * Each root node creates its own debugfs entry under <debugfs>/v4l2-memtrack/.
+ *
+ * Return: Pointer to the root node, or NULL on failure
+ */
+struct v4l2_memtrack_node *v4l2_memtrack_create_root(const char *name);
+
+/**
+ * v4l2_memtrack_create_node - Create a child tracking node
+ * @parent: Parent node
+ * @name: Optional name for this node
+ *
+ * Creates a child node under the specified parent. Child nodes
+ * contribute to their parent's total memory count.
+ *
+ * Return: Pointer to the new node, or NULL on failure
+ */
+struct v4l2_memtrack_node *v4l2_memtrack_create_node(struct v4l2_memtrack_node *parent,
+ const char *name);
+
+/**
+ * v4l2_memtrack_destroy_node - Destroy a tracking node
+ * @node: Node to destroy
+ *
+ * Destroys the node and all its children. If this is a root node,
+ * also removes the debugfs entry and frees all resources.
+ */
+void v4l2_memtrack_destroy_node(struct v4l2_memtrack_node *node);
+
+/**
+ * v4l2_memtrack_add - Record a memory allocation
+ * @node: Tracking node
+ * @bytes: Number of bytes allocated
+ * @name: Optional name for the allocation
+ *
+ * Records a memory allocation. If @name is provided, creates an internal
+ * leaf node to track this specific allocation, which can be matched and
+ * removed later by v4l2_memtrack_sub() with the same name and size.
+ * If @name is NULL, adds bytes directly to the node's counter.
+ *
+ * Triggers notification callbacks on this node and all ancestors.
+ */
+void v4l2_memtrack_add(struct v4l2_memtrack_node *node, size_t bytes,
+ const char *name);
+
+/**
+ * v4l2_memtrack_sub - Record a memory free
+ * @node: Tracking node
+ * @bytes: Number of bytes freed
+ * @name: Optional name to match (must match what was passed to add)
+ *
+ * Records a memory deallocation. If @name is provided, searches for a
+ * matching internal leaf node (by name and size) and removes it.
+ * If no match is found or @name is NULL, subtracts directly from the
+ * node's counter.
+ *
+ * Triggers notification callbacks on this node and all ancestors.
+ */
+void v4l2_memtrack_sub(struct v4l2_memtrack_node *node, size_t bytes,
+ const char *name);
+
+/**
+ * v4l2_memtrack_set - Set memory usage directly
+ * @node: Tracking node
+ * @bytes: Total bytes to set
+ *
+ * Sets the node's memory counter to the specified value.
+ * Allocation count is set to 1 if bytes > 0, otherwise 0.
+ */
+void v4l2_memtrack_set(struct v4l2_memtrack_node *node, size_t bytes);
+
+/**
+ * v4l2_memtrack_read - Read total memory usage
+ * @node: Tracking node
+ *
+ * Returns the total memory usage of this node plus all its children.
+ *
+ * Return: Total memory usage in bytes
+ */
+size_t v4l2_memtrack_read(struct v4l2_memtrack_node *node);
+
+/**
+ * v4l2_memtrack_register_notify - Register notification callback
+ * @node: Tracking node
+ * @notify: Callback function
+ * @priv: Private data passed to callback
+ *
+ * Register a callback that is called when memory usage changes on this
+ * node or any of its descendants. Only one callback per node is supported.
+ *
+ * Return: 0 on success, -EINVAL if node is invalid, -EBUSY if callback
+ * already registered
+ */
+int v4l2_memtrack_register_notify(struct v4l2_memtrack_node *node,
+ v4l2_memtrack_notify_fn notify,
+ void *priv);
+
+/**
+ * v4l2_memtrack_unregister_notify - Unregister notification callback
+ * @node: The tracking node
+ *
+ * Unregisters the notification callback and waits for any in-progress
+ * callback to complete.
+ *
+ * NOTE: This function MUST be called before v4l2_memtrack_destroy_node()
+ * if a notify callback was registered. Failing to do so will trigger
+ * a WARN and may cause use-after-free.
+ */
+void v4l2_memtrack_unregister_notify(struct v4l2_memtrack_node *node);
+
+/**
+ * v4l2_memtrack_set_notify_delay - Set notification delay
+ * @node: Any node in the tracking tree
+ * @delay_ms: Delay in milliseconds
+ * < 0: disable notifications
+ * = 0: immediate notification (default)
+ * > 0: coalesce notifications within delay period
+ *
+ * Sets the notification delay for the entire tracking tree.
+ * When delay > 0, multiple updates within the delay period are
+ * coalesced into a single notification, reducing overhead for
+ * batch operations.
+ */
+void v4l2_memtrack_set_notify_delay(struct v4l2_memtrack_node *node,
+ int delay_ms);
+
+/**
+ * v4l2_memtrack_print_debug - Print memory usage to kernel log
+ * @node: Tracking node
+ *
+ * Prints the memory usage tree starting from this node using pr_debug().
+ * Supports dynamic debug when CONFIG_DYNAMIC_DEBUG is enabled.
+ *
+ * Enable output with:
+ * echo 'file v4l2-memtrack.c +p' > /sys/kernel/debug/dynamic_debug/control
+ */
+void v4l2_memtrack_print_debug(struct v4l2_memtrack_node *node);
+
+#else /* !CONFIG_V4L2_MEMTRACK */
+
+static inline struct v4l2_memtrack_node *v4l2_memtrack_create_root(const char *name)
+{
+ return NULL;
+}
+
+static inline struct v4l2_memtrack_node *v4l2_memtrack_create_node(
+ struct v4l2_memtrack_node *parent, const char *name)
+{
+ return NULL;
+}
+
+static inline void v4l2_memtrack_destroy_node(struct v4l2_memtrack_node *node) {}
+
+static inline void v4l2_memtrack_add(struct v4l2_memtrack_node *node,
+ size_t bytes, const char *name) {}
+
+static inline void v4l2_memtrack_sub(struct v4l2_memtrack_node *node,
+ size_t bytes, const char *name) {}
+
+static inline void v4l2_memtrack_set(struct v4l2_memtrack_node *node, size_t bytes) {}
+
+static inline size_t v4l2_memtrack_read(struct v4l2_memtrack_node *node)
+{
+ return 0;
+}
+
+static inline int v4l2_memtrack_register_notify(struct v4l2_memtrack_node *node,
+ v4l2_memtrack_notify_fn notify,
+ void *priv)
+{
+ return 0;
+}
+
+static inline void v4l2_memtrack_unregister_notify(struct v4l2_memtrack_node *node) {}
+static inline void v4l2_memtrack_set_notify_delay(struct v4l2_memtrack_node *node, int delay_ms) {}
+static inline void v4l2_memtrack_print_debug(struct v4l2_memtrack_node *node) {}
+
+#endif /* CONFIG_V4L2_MEMTRACK */
+
+#endif /* _V4L2_MEMTRACK_H */
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* [RFC PATCH 4/7] docs: media: v4l2-memtrack: Add driver API documentation
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
` (2 preceding siblings ...)
2026-03-31 7:23 ` [RFC PATCH 3/7] media: v4l2-memtrack: Add V4L2 memory tracking infrastructure ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 7:23 ` [RFC PATCH 5/7] MAINTAINERS: Add entry for V4L2 memory usage tracker ming.qian
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add comprehensive documentation for the V4L2 memory tracking infrastructure
in the driver API documentation. This documentation covers:
- Overview of the hierarchical memory tracking system
- Basic usage examples showing root node creation and memory tracking
- Hierarchical tracking with parent-child node relationships
- debugfs interface for runtime memory inspection
- Notification callback registration and usage warnings
- Visual examples of tree structure and debugfs output
The documentation provides driver developers with practical examples
of how to integrate memory tracking into their V4L2 drivers, including
proper setup during probe/remove, buffer allocation tracking, and
per-context memory monitoring.
Add the new v4l2-memtrack documentation to the v4l2-core index to make
it accessible in the generated documentation.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
Documentation/driver-api/media/v4l2-core.rst | 1 +
.../driver-api/media/v4l2-memtrack.rst | 140 ++++++++++++++++++
2 files changed, 141 insertions(+)
create mode 100644 Documentation/driver-api/media/v4l2-memtrack.rst
diff --git a/Documentation/driver-api/media/v4l2-core.rst b/Documentation/driver-api/media/v4l2-core.rst
index a5f5102c64cc..09765d028375 100644
--- a/Documentation/driver-api/media/v4l2-core.rst
+++ b/Documentation/driver-api/media/v4l2-core.rst
@@ -28,3 +28,4 @@ Video4Linux devices
v4l2-tveeprom
v4l2-jpeg
v4l2-isp
+ v4l2-memtrack
diff --git a/Documentation/driver-api/media/v4l2-memtrack.rst b/Documentation/driver-api/media/v4l2-memtrack.rst
new file mode 100644
index 000000000000..bca6954cfa0b
--- /dev/null
+++ b/Documentation/driver-api/media/v4l2-memtrack.rst
@@ -0,0 +1,140 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+V4L2 Memory Usage Tracker
+=========================
+
+Overview
+--------
+
+The V4L2 memory tracking module provides hierarchical memory allocation
+tracking for V4L2 devices. It is useful for debugging memory leaks and
+monitoring buffer usage in video drivers.
+
+Features:
+
+- Tree-structured memory usage monitoring
+- Per-device and per-context tracking
+- debugfs interface for runtime inspection
+- Optional notification callbacks for memory changes
+- V4L2 control integration
+
+Usage Example
+-------------
+
+Basic usage in a V4L2 driver:
+
+.. code-block:: c
+
+ #include <media/v4l2-memtrack.h>
+
+ struct my_device {
+ struct v4l2_memtrack_node *memtrack;
+ /* ... */
+ };
+
+ static int my_probe(struct platform_device *pdev)
+ {
+ struct my_device *dev;
+
+ dev->memtrack = v4l2_memtrack_create_root("my-device");
+ if (!dev->memtrack)
+ return -ENOMEM;
+
+ return 0;
+ }
+
+ static void my_remove(struct platform_device *pdev)
+ {
+ v4l2_memtrack_destroy_node(dev->memtrack);
+ }
+
+ static int my_alloc_buffer(struct my_device *dev, size_t size)
+ {
+ void *buf = dma_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ v4l2_memtrack_add(dev->memtrack, size);
+ return 0;
+ }
+
+ static void my_free_buffer(struct my_device *dev, size_t size)
+ {
+ dma_free_coherent(dev, size, buf, dma_addr);
+ v4l2_memtrack_sub(dev->memtrack, size);
+ }
+
+Hierarchical Tracking
+---------------------
+
+For more detailed tracking, create child nodes:
+
+.. code-block:: c
+
+ struct my_context {
+ struct v4l2_memtrack_node *memtrack;
+ };
+
+ static int my_open(struct file *file)
+ {
+ struct my_context *ctx;
+
+ ctx->memtrack = v4l2_memtrack_create_node(dev->memtrack, "context");
+ return 0;
+ }
+
+ static int my_close(struct file *file)
+ {
+ v4l2_memtrack_destroy_node(ctx->memtrack);
+ return 0;
+ }
+
+This creates a tree structure::
+
+ my-device (root)
+ ├── context (pid=1234)
+ │ ├── buffer: 4096 bytes
+ │ └── buffer: 8192 bytes
+ └── context (pid=5678)
+ └── buffer: 4096 bytes
+
+debugfs Interface
+-----------------
+
+Memory usage is exposed via debugfs at::
+
+ /sys/kernel/debug/v4l2-memtrack/<device-name>
+
+Example output::
+
+ Total memory usage: 16384 bytes
+ my-device (tgid=1000, pid=1000) usage: 16384
+ context (tgid=1234, pid=1234) usage: 12288 (count=2)
+ context (tgid=5678, pid=5678) usage: 4096 (count=1)
+
+Notification Callbacks
+----------------------
+
+Register callbacks to be notified of memory changes:
+
+.. code-block:: c
+
+ static void my_notify(struct v4l2_memtrack_node *node,
+ size_t total, void *priv)
+ {
+ pr_info("Memory usage changed: %zu bytes\n", total);
+ }
+
+ v4l2_memtrack_register_notify(dev->memtrack, my_notify, dev);
+
+.. warning::
+
+ Callbacks are executed without holding internal locks, so most kernel
+ functions may be called safely. However, the callback MUST NOT call
+ v4l2_memtrack_unregister_notify() or v4l2_memtrack_destroy_node() on
+ the same node, as this will cause a deadlock.
+
+API Reference
+-------------
+
+.. kernel-doc:: include/media/v4l2-memtrack.h
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* [RFC PATCH 5/7] MAINTAINERS: Add entry for V4L2 memory usage tracker
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
` (3 preceding siblings ...)
2026-03-31 7:23 ` [RFC PATCH 4/7] docs: media: v4l2-memtrack: Add driver API documentation ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 7:23 ` [RFC PATCH 6/7] media: videobuf2: Add memory tracking support ming.qian
2026-03-31 7:23 ` [RFC PATCH 7/7] media: amphion: Add V4L2 " ming.qian
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add a MAINTAINERS entry for the V4L2 memory tracking infrastructure,
covering the driver API documentation, core implementation, and header
files.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
MAINTAINERS | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 32b1dfee8614..6de2f259415f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -27667,6 +27667,14 @@ F: drivers/media/v4l2-core/v4l2-isp.c
F: include/media/v4l2-isp.h
F: include/uapi/linux/media/v4l2-isp.h
+V4L2 MEMORY USAGE TRACKER
+M: Ming Qian <ming.qian@oss.nxp.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+F: Documentation/driver-api/media/v4l2-memtrack.rst
+F: drivers/media/common/v4l2-memtrack/v4l2-memtrack.c
+F: include/media/v4l2-memtrack.h
+
VF610 NAND DRIVER
M: Stefan Agner <stefan@agner.ch>
L: linux-mtd@lists.infradead.org
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* [RFC PATCH 6/7] media: videobuf2: Add memory tracking support
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
` (4 preceding siblings ...)
2026-03-31 7:23 ` [RFC PATCH 5/7] MAINTAINERS: Add entry for V4L2 memory usage tracker ming.qian
@ 2026-03-31 7:23 ` ming.qian
2026-03-31 7:23 ` [RFC PATCH 7/7] media: amphion: Add V4L2 " ming.qian
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Add optional memtrack field to vb2_queue for tracking MMAP buffer
memory usage. When a driver sets q->memtrack, the core automatically
tracks allocations via v4l2_memtrack_add/sub calls.
Only MMAP type buffers are tracked since DMABUF memory is allocated
externally by userspace.
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
drivers/media/common/videobuf2/videobuf2-core.c | 13 +++++++++++++
include/media/videobuf2-core.h | 4 ++++
2 files changed, 17 insertions(+)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index adf668b213c2..e42fdf829b22 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -28,6 +28,7 @@
#include <media/videobuf2-core.h>
#include <media/v4l2-mc.h>
+#include <media/v4l2-memtrack.h>
#include <trace/events/vb2.h>
@@ -251,12 +252,19 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
/* Associate allocator private data with this plane */
vb->planes[plane].mem_priv = mem_priv;
+
+ if (q->memtrack)
+ v4l2_memtrack_add(q->memtrack, size, NULL);
}
return 0;
free:
/* Free already allocated memory if one of the allocations failed */
for (; plane > 0; --plane) {
+ unsigned long size = PAGE_ALIGN(vb->planes[plane - 1].length);
+
+ if (q->memtrack)
+ v4l2_memtrack_sub(q->memtrack, size, NULL);
call_void_memop(vb, put, vb->planes[plane - 1].mem_priv);
vb->planes[plane - 1].mem_priv = NULL;
}
@@ -269,9 +277,14 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
*/
static void __vb2_buf_mem_free(struct vb2_buffer *vb)
{
+ struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
for (plane = 0; plane < vb->num_planes; ++plane) {
+ unsigned long size = PAGE_ALIGN(vb->planes[plane].length);
+
+ if (q->memtrack)
+ v4l2_memtrack_sub(q->memtrack, size, NULL);
call_void_memop(vb, put, vb->planes[plane].mem_priv);
vb->planes[plane].mem_priv = NULL;
dprintk(vb->vb2_queue, 3, "freed plane %d of buffer %d\n",
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 4424d481d7f7..7cb6ff2fc892 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -47,6 +47,7 @@ enum vb2_memory {
struct vb2_fileio_data;
struct vb2_threadio_data;
struct vb2_buffer;
+struct v4l2_memtrack_node;
/**
* struct vb2_mem_ops - memory handling/memory allocator operations.
@@ -558,6 +559,7 @@ struct vb2_buf_ops {
* driver implements the V4L2_CID_MIN_BUFFERS_FOR_CAPTURE/OUTPUT
* control.
* @alloc_devs: &struct device memory type/allocator-specific per-plane device
+ * @memtrack: optional memory tracking node for debugging and monitoring.
*/
/*
* Private elements (won't appear at the uAPI book):
@@ -632,6 +634,8 @@ struct vb2_queue {
struct device *alloc_devs[VB2_MAX_PLANES];
+ struct v4l2_memtrack_node *memtrack;
+
/* private: internal use only */
struct mutex mmap_lock;
unsigned int memory;
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread* [RFC PATCH 7/7] media: amphion: Add V4L2 memory tracking support
2026-03-31 7:23 [RFC PATCH 0/7] media: amphion: Add DMA memory tracking support ming.qian
` (5 preceding siblings ...)
2026-03-31 7:23 ` [RFC PATCH 6/7] media: videobuf2: Add memory tracking support ming.qian
@ 2026-03-31 7:23 ` ming.qian
6 siblings, 0 replies; 16+ messages in thread
From: ming.qian @ 2026-03-31 7:23 UTC (permalink / raw)
To: linux-media
Cc: mchehab, hverkuil-cisco, nicolas, sebastian.fricke, shawnguo,
s.hauer, kernel, festevam, linux-imx, Frank.li, xiahong.bao,
eagle.zhou, imx, linux-kernel, linux-arm-kernel
From: Ming Qian <ming.qian@oss.nxp.com>
Integrate V4L2 memtrack framework to track DMA buffer allocations in the
Amphion VPU driver. Memory usage is organized hierarchically (device ->
instance -> queue) and exposed via V4L2_CID_MEMORY_USAGE control and
debugfs.
Tracked buffers include firmware boot region, RPC, stream ring buffers,
and codec-specific frame buffers (MBI, DCP, enc/ref frames).
Signed-off-by: Ming Qian <ming.qian@oss.nxp.com>
---
drivers/media/platform/amphion/Kconfig | 1 +
drivers/media/platform/amphion/vdec.c | 9 ++++++
drivers/media/platform/amphion/venc.c | 9 ++++++
drivers/media/platform/amphion/vpu.h | 7 +++++
drivers/media/platform/amphion/vpu_core.c | 6 ++++
drivers/media/platform/amphion/vpu_dbg.c | 5 ++++
drivers/media/platform/amphion/vpu_drv.c | 2 ++
drivers/media/platform/amphion/vpu_v4l2.c | 35 ++++++++++++++++++++++-
8 files changed, 73 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/amphion/Kconfig b/drivers/media/platform/amphion/Kconfig
index 4a363e07ccc9..2835c25415c5 100644
--- a/drivers/media/platform/amphion/Kconfig
+++ b/drivers/media/platform/amphion/Kconfig
@@ -12,6 +12,7 @@ config VIDEO_AMPHION_VPU
select V4L2_MEM2MEM_DEV
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
+ select V4L2_MEMTRACK
help
Amphion VPU Codec IP contains two parts: Windsor and Malone.
Windsor is encoder that supports H.264, and Malone is decoder
diff --git a/drivers/media/platform/amphion/vdec.c b/drivers/media/platform/amphion/vdec.c
index a9f0521f2e1a..2b863fadb67f 100644
--- a/drivers/media/platform/amphion/vdec.c
+++ b/drivers/media/platform/amphion/vdec.c
@@ -279,6 +279,9 @@ static int vdec_ctrl_init(struct vpu_inst *inst)
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
+ V4L2_CID_MEMORY_USAGE, 0, S64_MAX, 1, 0);
+
if (inst->ctrl_handler.error) {
ret = inst->ctrl_handler.error;
v4l2_ctrl_handler_free(&inst->ctrl_handler);
@@ -1069,6 +1072,8 @@ static int vdec_alloc_fs_buffer(struct vpu_inst *inst, struct vdec_fs_info *fs)
vpu_free_dma(buffer);
buffer->length = fs->size;
+ buffer->memtrack = inst->memtrack;
+ buffer->label = fs->type == MEM_RES_MBI ? "mbi" : "dcp";
return vpu_alloc_dma(inst->core, buffer);
}
@@ -1683,6 +1688,8 @@ static int vdec_start(struct vpu_inst *inst)
vpu_trace(inst->dev, "[%d]\n", inst->id);
if (!vdec->udata.virt) {
vdec->udata.length = 0x1000;
+ vdec->udata.memtrack = inst->memtrack;
+ vdec->udata.label = "udata";
ret = vpu_alloc_dma(inst->core, &vdec->udata);
if (ret) {
dev_err(inst->dev, "[%d] alloc udata fail\n", inst->id);
@@ -1694,6 +1701,8 @@ static int vdec_start(struct vpu_inst *inst)
stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core);
if (stream_buffer_size > 0) {
inst->stream_buffer.length = stream_buffer_size;
+ inst->stream_buffer.memtrack = inst->memtrack;
+ inst->stream_buffer.label = "bitstream-ring-buffer";
ret = vpu_alloc_dma(inst->core, &inst->stream_buffer);
if (ret) {
dev_err(inst->dev, "[%d] alloc stream buffer fail\n", inst->id);
diff --git a/drivers/media/platform/amphion/venc.c b/drivers/media/platform/amphion/venc.c
index 0b3d58b9f2f7..193ee488eba4 100644
--- a/drivers/media/platform/amphion/venc.c
+++ b/drivers/media/platform/amphion/venc.c
@@ -678,6 +678,9 @@ static int venc_ctrl_init(struct vpu_inst *inst)
v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
V4L2_CID_MPEG_VIDEO_AVERAGE_QP, 0, 51, 1, 0);
+ v4l2_ctrl_new_std(&inst->ctrl_handler, NULL,
+ V4L2_CID_MEMORY_USAGE, 0, S64_MAX, 1, 0);
+
if (inst->ctrl_handler.error) {
ret = inst->ctrl_handler.error;
v4l2_ctrl_handler_free(&inst->ctrl_handler);
@@ -929,6 +932,8 @@ static int venc_start_session(struct vpu_inst *inst, u32 type)
stream_buffer_size = vpu_iface_get_stream_buffer_size(inst->core);
if (stream_buffer_size > 0) {
inst->stream_buffer.length = max_t(u32, stream_buffer_size, venc->cpb_size * 3);
+ inst->stream_buffer.memtrack = inst->memtrack;
+ inst->stream_buffer.label = "bitstream-ring-buffer";
ret = vpu_alloc_dma(inst->core, &inst->stream_buffer);
if (ret)
goto error;
@@ -1027,6 +1032,8 @@ static void venc_request_mem_resource(struct vpu_inst *inst,
for (i = 0; i < enc_frame_num; i++) {
venc->enc[i].length = enc_frame_size;
+ venc->enc[i].memtrack = inst->memtrack;
+ venc->enc[i].label = "enc-frame";
ret = vpu_alloc_dma(inst->core, &venc->enc[i]);
if (ret) {
venc_cleanup_mem_resource(inst);
@@ -1035,6 +1042,8 @@ static void venc_request_mem_resource(struct vpu_inst *inst,
}
for (i = 0; i < ref_frame_num; i++) {
venc->ref[i].length = ref_frame_size;
+ venc->ref[i].memtrack = inst->memtrack;
+ venc->ref[i].label = "ref-frame";
ret = vpu_alloc_dma(inst->core, &venc->ref[i]);
if (ret) {
venc_cleanup_mem_resource(inst);
diff --git a/drivers/media/platform/amphion/vpu.h b/drivers/media/platform/amphion/vpu.h
index bfd171a3ded4..08913cc54cb1 100644
--- a/drivers/media/platform/amphion/vpu.h
+++ b/drivers/media/platform/amphion/vpu.h
@@ -9,6 +9,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-memtrack.h>
#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#include <linux/kfifo.h>
@@ -17,6 +18,7 @@
#define VPU_TIMEOUT msecs_to_jiffies(1000)
#define VPU_INST_NULL_ID (-1L)
#define VPU_MSG_BUFFER_SIZE (8192)
+#define VPU_NOTIFY_DELAY_MS (200)
enum imx_plat_type {
IMX8QXP = 0,
@@ -47,6 +49,8 @@ struct vpu_buffer {
u32 length;
u32 bytesused;
struct device *dev;
+ struct v4l2_memtrack_node *memtrack;
+ const char *label;
};
struct vpu_func {
@@ -81,6 +85,7 @@ struct vpu_dev {
atomic_t ref_dec;
struct dentry *debugfs;
+ struct v4l2_memtrack_node *memtrack;
};
struct vpu_format {
@@ -279,6 +284,8 @@ struct vpu_inst {
pid_t tgid;
struct dentry *debugfs;
+ struct v4l2_memtrack_node *memtrack;
+
void *priv;
};
diff --git a/drivers/media/platform/amphion/vpu_core.c b/drivers/media/platform/amphion/vpu_core.c
index 85cc4a14f8ed..16c2efc86feb 100644
--- a/drivers/media/platform/amphion/vpu_core.c
+++ b/drivers/media/platform/amphion/vpu_core.c
@@ -150,6 +150,8 @@ static int __vpu_alloc_dma(struct device *dev, struct vpu_buffer *buf)
if (!buf->virt)
return -ENOMEM;
+ if (buf->memtrack)
+ v4l2_memtrack_add(buf->memtrack, buf->length, buf->label);
buf->dev = dev;
return 0;
@@ -160,6 +162,8 @@ void vpu_free_dma(struct vpu_buffer *buf)
if (!buf->virt || !buf->dev)
return;
+ if (buf->memtrack)
+ v4l2_memtrack_sub(buf->memtrack, buf->length, buf->label);
dma_free_coherent(buf->dev, buf->length, buf->virt, buf->phys);
buf->virt = NULL;
buf->phys = 0;
@@ -550,6 +554,7 @@ static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np)
core->fw.phys = res.start;
core->fw.length = resource_size(&res);
+ v4l2_memtrack_add(core->vpu->memtrack, core->fw.length, "fw");
ret = of_reserved_mem_region_to_resource(np, 1, &res);
if (ret) {
@@ -559,6 +564,7 @@ static int vpu_core_parse_dt(struct vpu_core *core, struct device_node *np)
core->rpc.phys = res.start;
core->rpc.length = resource_size(&res);
+ v4l2_memtrack_add(core->vpu->memtrack, core->rpc.length, "rpc");
if (core->rpc.length < core->res->rpc_size + core->res->fwlog_size) {
dev_err(core->dev, "the rpc-region <%pad, 0x%x> is not enough\n",
diff --git a/drivers/media/platform/amphion/vpu_dbg.c b/drivers/media/platform/amphion/vpu_dbg.c
index 497ae4e8a229..a82e21cc8a67 100644
--- a/drivers/media/platform/amphion/vpu_dbg.c
+++ b/drivers/media/platform/amphion/vpu_dbg.c
@@ -212,6 +212,11 @@ static int vpu_dbg_instance(struct seq_file *s, void *data)
if (seq_write(s, str, num))
return 0;
+ num = scnprintf(str, sizeof(str), "memory usage = %ld\n",
+ v4l2_memtrack_read(inst->memtrack));
+ if (seq_write(s, str, num))
+ return 0;
+
num = scnprintf(str, sizeof(str), "flow :\n");
if (seq_write(s, str, num))
return 0;
diff --git a/drivers/media/platform/amphion/vpu_drv.c b/drivers/media/platform/amphion/vpu_drv.c
index 2cca61f41bea..73e01c55da82 100644
--- a/drivers/media/platform/amphion/vpu_drv.c
+++ b/drivers/media/platform/amphion/vpu_drv.c
@@ -138,6 +138,7 @@ static int vpu_probe(struct platform_device *pdev)
if (ret)
goto err_vpu_media;
vpu->debugfs = debugfs_create_dir("amphion_vpu", NULL);
+ vpu->memtrack = v4l2_memtrack_create_root("amphion-vpu");
of_platform_populate(dev->of_node, NULL, NULL, dev);
@@ -162,6 +163,7 @@ static void vpu_remove(struct platform_device *pdev)
struct vpu_dev *vpu = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
+ v4l2_memtrack_destroy_node(vpu->memtrack);
debugfs_remove_recursive(vpu->debugfs);
vpu->debugfs = NULL;
diff --git a/drivers/media/platform/amphion/vpu_v4l2.c b/drivers/media/platform/amphion/vpu_v4l2.c
index 7cccc994fc50..431f5f64e683 100644
--- a/drivers/media/platform/amphion/vpu_v4l2.c
+++ b/drivers/media/platform/amphion/vpu_v4l2.c
@@ -651,6 +651,14 @@ static const struct vb2_ops vpu_vb2_ops = {
.buf_queue = vpu_vb2_buf_queue,
};
+static void vpu_memtrack_ctrl_notify(struct v4l2_memtrack_node *node, size_t total, void *priv)
+{
+ struct v4l2_ctrl *ctrl = priv;
+
+ if (ctrl)
+ v4l2_ctrl_s_ctrl_int64(ctrl, total);
+}
+
static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
{
struct vpu_inst *inst = priv;
@@ -668,9 +676,13 @@ static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_q
src_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer);
src_vq->dev = inst->vpu->dev;
src_vq->lock = &inst->lock;
+ if (inst->memtrack)
+ src_vq->memtrack = v4l2_memtrack_create_node(inst->memtrack, "output");
ret = vb2_queue_init(src_vq);
- if (ret)
+ if (ret) {
+ v4l2_memtrack_destroy_node(src_vq->memtrack);
return ret;
+ }
dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
inst->cap_format.type = dst_vq->type;
@@ -684,8 +696,12 @@ static int vpu_m2m_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_q
dst_vq->buf_struct_size = sizeof(struct vpu_vb2_buffer);
dst_vq->dev = inst->vpu->dev;
dst_vq->lock = &inst->lock;
+ if (inst->memtrack)
+ dst_vq->memtrack = v4l2_memtrack_create_node(inst->memtrack, "capture");
ret = vb2_queue_init(dst_vq);
if (ret) {
+ v4l2_memtrack_destroy_node(src_vq->memtrack);
+ v4l2_memtrack_destroy_node(dst_vq->memtrack);
vb2_queue_release(src_vq);
return ret;
}
@@ -706,6 +722,12 @@ static int vpu_v4l2_release(struct vpu_inst *inst)
vpu_release_core(inst->core);
put_device(inst->dev);
+ if (inst->memtrack) {
+ v4l2_memtrack_unregister_notify(inst->memtrack);
+ v4l2_memtrack_destroy_node(inst->memtrack);
+ inst->memtrack = NULL;
+ }
+
v4l2_ctrl_handler_free(&inst->ctrl_handler);
mutex_destroy(&inst->lock);
@@ -745,6 +767,8 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst)
inst->min_buffer_out = 2;
v4l2_fh_init(&inst->fh, func->vfd);
v4l2_fh_add(&inst->fh, file);
+ if (vpu->memtrack)
+ inst->memtrack = v4l2_memtrack_create_node(vpu->memtrack, "instance");
ret = call_vop(inst, ctrl_init);
if (ret)
@@ -757,6 +781,14 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst)
goto error;
}
+ if (inst->memtrack) {
+ v4l2_memtrack_set_notify_delay(inst->memtrack, VPU_NOTIFY_DELAY_MS);
+ v4l2_memtrack_register_notify(inst->memtrack,
+ vpu_memtrack_ctrl_notify,
+ v4l2_ctrl_find(&inst->ctrl_handler,
+ V4L2_CID_MEMORY_USAGE));
+ }
+
inst->fh.ctrl_handler = &inst->ctrl_handler;
inst->state = VPU_CODEC_STATE_DEINIT;
inst->workqueue = alloc_ordered_workqueue("vpu_inst", WQ_MEM_RECLAIM);
@@ -775,6 +807,7 @@ int vpu_v4l2_open(struct file *file, struct vpu_inst *inst)
return 0;
error:
+ v4l2_memtrack_destroy_node(inst->memtrack);
v4l2_fh_del(&inst->fh, file);
v4l2_fh_exit(&inst->fh);
vpu_inst_put(inst);
--
2.53.0
^ permalink raw reply related [flat|nested] 16+ messages in thread