* Re: [PATCH v2 1/4] virtio-mem: validate device-reported block size
From: Greg Kroah-Hartman @ 2026-07-18 5:29 UTC (permalink / raw)
To: Carlos Bilbao
Cc: Michael S. Tsirkin, David Hildenbrand (Arm), Hari Mishal,
Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization,
linux-kernel, elena.reshetova
In-Reply-To: <1fe328d1-edf9-4e72-a145-be74ede20e60@gmail.com>
On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
> Historically, one of the biggest criticisms of coco, especially around
> device hardening, was that there were too many values that a
> malicious/buggy device could misreport, making it a losing battle. That is
> no longer the case with LLMs, and we have the advantage (and challenge) of
> open-source dev, which allows us to receive many of these fixes "for free".
> If others want to burn their tokens, let them :)
I have lots of tokens to burn :)
So along those lines, any suggestions on how best to fuzz these code
paths? Any workloads you all use for testing that I can take advantage
of?
thanks,
greg k-h
^ permalink raw reply
* Re: [PATCH v2 1/4] virtio-mem: validate device-reported block size
From: Carlos Bilbao @ 2026-07-18 17:07 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Michael S. Tsirkin, David Hildenbrand (Arm), Hari Mishal,
Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization,
linux-kernel, elena.reshetova, huster, mhollick, jiska.classen
In-Reply-To: <2026071803-passage-dares-8240@gregkh>
On 7/17/26 22:29, Greg Kroah-Hartman wrote:
> On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
>> Historically, one of the biggest criticisms of coco, especially around
>> device hardening, was that there were too many values that a
>> malicious/buggy device could misreport, making it a losing battle. That is
>> no longer the case with LLMs, and we have the advantage (and challenge) of
>> open-source dev, which allows us to receive many of these fixes "for free".
>> If others want to burn their tokens, let them :)
> I have lots of tokens to burn :)
>
> So along those lines, any suggestions on how best to fuzz these code
> paths? Any workloads you all use for testing that I can take advantage
> of?
We've the virtio-mem config struct layout and the kernel source, so for
obvious fixes like a NULL check, static analysis is better than fuzzing.
Claude took a few mins to find me two examples:
Patch 1: virtio-mem: reject non-power-of-two device_block_size
This one is for virtio_mem_init() to check if
!is_power_of_2(vm->device_block_size)
Patch 2: virto-mem: validate region_size and usable_region_size
THis one checks region_size != 0 and vm->usable_reion_size >
vm->region_size.
An endless factory of "silly" checks like these are low hanging fruit.
Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
like a great candidate for those interested in pursuing this direction.
Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
can't quickly adapt for virtio-mem and other virtio drivers; the JSON
definition to describe device behavior is easily extensible. Their threat
model [2] describes an external attacker, but in the context of coco, the
virtio device itself is the attacker. Here's a vibe coded PR of what I mean:
https://github.com/seemoo-lab/VirtFuzz/pull/7
CCed the creators/authors, thanks for open sourcing this!
Thanks,
Carlos
[1] https://github.com/seemoo-lab/VirtFuzz
On 7/17/26 22:29, Greg Kroah-Hartman wrote:
> On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
>> Historically, one of the biggest criticisms of coco, especially around
>> device hardening, was that there were too many values that a
>> malicious/buggy device could misreport, making it a losing battle. That is
>> no longer the case with LLMs, and we have the advantage (and challenge) of
>> open-source dev, which allows us to receive many of these fixes "for free".
>> If others want to burn their tokens, let them :)
> I have lots of tokens to burn :)
>
> So along those lines, any suggestions on how best to fuzz these code
> paths? Any workloads you all use for testing that I can take advantage
> of?
We've the virto-mem config struct layout and the kernel source, so for
obvious fixes like a NULL check, static analysis is better than fuzzing.
Claude took a few mins to find me two examples:
Patch 1: virtio-mem: reject non-power-of-two device_block_size
This one is for virtio_mem_init() to check if
!is_power_of_2(vm->device_block_size)
Patch 2: virto-mem: validate region_size and usable_region_size
THis one checks region_size != 0 and vm->usable_reion_size >
vm->region_size.
An endless factory of "silly" checks like these are low hanging fruit.
Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
like a great candidate for those interested in pursuing this direction.
Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
can't quickly adapt for virtio-mem and other virtio drivers; the JSON
definition to describe device behavior is easily extensible. Their threat
model [2] describes an external attacker, but in the context of coco, the
virtio device itself is the attacker. Here's a vibe coded PR of what I mean:
https://github.com/seemoo-lab/VirtFuzz/pull/7
CCed the creators/authors, thanks for open sourcing this!
Thanks,
Carlos
[1] https://github.com/seemoo-lab/VirtFuzz
[2]
https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
> thanks,
>
> greg k-h
[2]
https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
>
> thanks,
>
> greg k-h
^ permalink raw reply
* Re: [PATCH v2 1/4] virtio-mem: validate device-reported block size
From: Michael S. Tsirkin @ 2026-07-18 17:21 UTC (permalink / raw)
To: Carlos Bilbao
Cc: Greg Kroah-Hartman, David Hildenbrand (Arm), Hari Mishal,
Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization,
linux-kernel, elena.reshetova, huster, mhollick, jiska.classen
In-Reply-To: <ae5bc86b-cb8d-4530-9e58-d285007deac0@gmail.com>
On Sat, Jul 18, 2026 at 10:07:30AM -0700, Carlos Bilbao wrote:
> On 7/17/26 22:29, Greg Kroah-Hartman wrote:
>
> > On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
> > > Historically, one of the biggest criticisms of coco, especially around
> > > device hardening, was that there were too many values that a
> > > malicious/buggy device could misreport, making it a losing battle. That is
> > > no longer the case with LLMs, and we have the advantage (and challenge) of
> > > open-source dev, which allows us to receive many of these fixes "for free".
> > > If others want to burn their tokens, let them :)
> > I have lots of tokens to burn :)
> >
> > So along those lines, any suggestions on how best to fuzz these code
> > paths? Any workloads you all use for testing that I can take advantage
> > of?
>
>
> We've the virtio-mem config struct layout and the kernel source, so for
> obvious fixes like a NULL check, static analysis is better than fuzzing.
> Claude took a few mins to find me two examples:
>
> Patch 1: virtio-mem: reject non-power-of-two device_block_size
> This one is for virtio_mem_init() to check if
> !is_power_of_2(vm->device_block_size)
>
> Patch 2: virto-mem: validate region_size and usable_region_size
> THis one checks region_size != 0 and vm->usable_reion_size >
> vm->region_size.
>
> An endless factory of "silly" checks like these are low hanging fruit.
At the same time, these checks don't actually help within the coco
threat model, do they?
> Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
> like a great candidate for those interested in pursuing this direction.
>
>
> Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
> can't quickly adapt for virtio-mem and other virtio drivers; the JSON
> definition to describe device behavior is easily extensible. Their threat
> model [2] describes an external attacker, but in the context of coco, the
> virtio device itself is the attacker.
What we need, however, is to exclude DoS attacks - these are outside the
threat model. If people try to address all DoS attacks uncritically we
just get a churn of changes which just might introduce issues of their
own.
Example:
BUG_ON(!is_power_of_2(....));
panics, non exploitable.
if(!is_power_of_2(....))
goto error;
can become exploitable if the cleanup is done wrong.
> Here's a vibe coded PR of what I mean:
>
> https://github.com/seemoo-lab/VirtFuzz/pull/7
>
> CCed the creators/authors, thanks for open sourcing this!
>
> Thanks,
> Carlos
>
> [1] https://github.com/seemoo-lab/VirtFuzz
>
> On 7/17/26 22:29, Greg Kroah-Hartman wrote:
>
> > On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
> > > Historically, one of the biggest criticisms of coco, especially around
> > > device hardening, was that there were too many values that a
> > > malicious/buggy device could misreport, making it a losing battle. That is
> > > no longer the case with LLMs, and we have the advantage (and challenge) of
> > > open-source dev, which allows us to receive many of these fixes "for free".
> > > If others want to burn their tokens, let them :)
> > I have lots of tokens to burn :)
> >
> > So along those lines, any suggestions on how best to fuzz these code
> > paths? Any workloads you all use for testing that I can take advantage
> > of?
>
>
> We've the virto-mem config struct layout and the kernel source, so for
> obvious fixes like a NULL check, static analysis is better than fuzzing.
> Claude took a few mins to find me two examples:
>
> Patch 1: virtio-mem: reject non-power-of-two device_block_size
> This one is for virtio_mem_init() to check if
> !is_power_of_2(vm->device_block_size)
>
> Patch 2: virto-mem: validate region_size and usable_region_size
> THis one checks region_size != 0 and vm->usable_reion_size >
> vm->region_size.
>
> An endless factory of "silly" checks like these are low hanging fruit.
>
> Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
> like a great candidate for those interested in pursuing this direction.
>
>
> Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
> can't quickly adapt for virtio-mem and other virtio drivers; the JSON
> definition to describe device behavior is easily extensible. Their threat
> model [2] describes an external attacker, but in the context of coco, the
> virtio device itself is the attacker. Here's a vibe coded PR of what I mean:
>
> https://github.com/seemoo-lab/VirtFuzz/pull/7
>
> CCed the creators/authors, thanks for open sourcing this!
>
> Thanks,
> Carlos
>
> [1] https://github.com/seemoo-lab/VirtFuzz
> [2] https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
>
>
> > thanks,
> >
> > greg k-h
>
> [2] https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
>
>
> >
> > thanks,
> >
> > greg k-h
^ permalink raw reply
* Re: [PATCH v4 2/8] media: virtio: Add virtio-media driver structs and function declarations
From: Michael S. Tsirkin @ 2026-07-18 17:27 UTC (permalink / raw)
To: Brian Daniels
Cc: Mauro Carvalho Chehab, acourbot, adelva, aesteve, changyeon,
daniel.almeida, eperezma, gnurou, gurchetansingh, hverkuil,
jasowang, linux-kernel, linux-media, nicolas.dufresne,
virtualization, xuanzhuo
In-Reply-To: <CAD4i_GTBkZRAnBTohkzJSh2XTx+MHkTS_KokEMQ4s0-WP+DxcA@mail.gmail.com>
On Fri, Jul 17, 2026 at 03:46:36PM -0400, Brian Daniels wrote:
> On Mon, Jun 22, 2026 at 5:08 PM Michael S. Tsirkin <mst@redhat.com> wrote:
> >
> > On Mon, Jun 22, 2026 at 04:43:37PM -0400, Brian Daniels wrote:
> > > From: Alexandre Courbot <gnurou@gmail.com>
> > >
> > > Add the structs and function declarations for the new virtio-media drvier.
> > >
> > > Signed-off-by: Alexandre Courbot <gnurou@gmail.com>
> > > Co-developed-by: Brian Daniels <briandaniels@google.com>
> > > Signed-off-by: Brian Daniels <briandaniels@google.com>
> > > ---
> > > drivers/media/virtio/virtio_media.h | 95 +++++++++++++++++++++++++++++
> > > 1 file changed, 95 insertions(+)
> > > create mode 100644 drivers/media/virtio/virtio_media.h
> > >
> > > diff --git a/drivers/media/virtio/virtio_media.h b/drivers/media/virtio/virtio_media.h
> > > new file mode 100644
> > > index 000000000..52809d4e9
> > > --- /dev/null
> > > +++ b/drivers/media/virtio/virtio_media.h
> > > @@ -0,0 +1,95 @@
> > > +/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+ */
> > > +
> > > +/*
> > > + * Virtio-media structures & functions declarations.
> > > + *
> > > + * Copyright (c) 2024-2025 Google LLC.
> > > + */
> > > +
> > > +#ifndef __VIRTIO_MEDIA_H
> > > +#define __VIRTIO_MEDIA_H
> > > +
> > > +#include <linux/virtio_config.h>
> > > +#include <media/v4l2-device.h>
> > > +
> > > +#include "protocol.h"
> > > +
> > > +#define DESC_CHAIN_MAX_LEN SG_MAX_SINGLE_ALLOC
> > > +
> > > +#define VIRTIO_MEDIA_DEFAULT_DRIVER_NAME "virtio-media"
> > > +
> > > +extern char *virtio_media_driver_name;
> > > +extern bool virtio_media_allow_userptr;
> > > +
> > > +/**
> > > + * struct virtio_media - Virtio-media device.
> > > + * @v4l2_dev: v4l2_device for the media device.
> > > + * @video_dev: video_device for the media device.
> > > + * @virtio_dev: virtio device for the media device.
> > > + * @commandq: virtio command queue.
> > > + * @eventq: virtio event queue.
> > > + * @eventq_work: work to run when events are received on @eventq.
> > > + * @mmap_region: region into which MMAP buffers are mapped by the host.
> > > + * @event_buffer: buffer for event descriptors.
> > > + * @sessions: list of active sessions on the device.
> > > + * @sessions_lock: protects @sessions and ``virtio_media_session::list``.
> > > + * @events_lock: prevents concurrent processing of events.
> > > + * @cmd: union of the device commands "open" and "munmap". The other
> > > + * commands are handled by @struct virtio_media_session
> > > + * @resp: union of responses.to device commands "open" and "munmap". The
> > > + * other responses are handled by @struct virtio_media_session
> > > + * @vlock: serializes access to the command queue.
> > > + * @wq: waitqueue for host responses on the command queue.
> > > + */
> > > +struct virtio_media {
> > > + struct v4l2_device v4l2_dev;
> > > + struct video_device video_dev;
> > > +
> > > + struct virtio_device *virtio_dev;
> > > + struct virtqueue *commandq;
> > > + struct virtqueue *eventq;
> > > + struct work_struct eventq_work;
> > > +
> > > + struct virtio_shm_region mmap_region;
> > > +
> > > + void *event_buffer;
> > > +
> > > + struct list_head sessions;
> > > + struct mutex sessions_lock; /* protects sessions list */
> > > +
> > > + struct mutex events_lock; /* prevents concurrent event processing */
> > > +
> > > + union {
> > > + struct virtio_media_cmd_open open;
> > > + struct virtio_media_cmd_munmap munmap;
> > > + } cmd;
> > > +
> > > + union {
> > > + struct virtio_media_resp_open open;
> > > + struct virtio_media_resp_munmap munmap;
> > > + } resp;
> >
> >
> > You need DMA alignment padding for these things.
>
> Each member of the above unions is already padded to 64-bit alignment,
> is that sufficient?
>
> If not, could you tell me what else is necessary?
Read up "What memory is DMA'able?" and following chapters in
Documentation/core-api/dma-api-howto.rst
> > Which one can only see when I reads the actual driver 8 patches down.
> > Which is why it's not a sensible way to split patches.
> >
> > A sensible way is to have a driver then add functionality
> > in logical pieces gradually.
> >
>
> Appreciate the feedback. There was a previous comment requesting to
> split the patch into c/h file pairs, but I can try reformatting it as
> you suggest for v5.
>
> > > +
> > > + struct mutex vlock; /* serializes command queue access */
> > > + wait_queue_head_t wq;
> > > +};
> > > +
> > > +static inline struct virtio_media *
> > > +to_virtio_media(struct video_device *video_dev)
> > > +{
> > > + return container_of(video_dev, struct virtio_media, video_dev);
> > > +}
> > > +
> > > +/* virtio_media_driver.c */
> > > +
> > > +int virtio_media_send_command(struct virtio_media *vv, struct scatterlist **sgs,
> > > + const size_t out_sgs, const size_t in_sgs,
> > > + size_t minimum_resp_len, size_t *resp_len);
> > > +void virtio_media_process_events(struct virtio_media *vv);
> > > +
> > > +/* virtio_media_ioctls.c */
> > > +
> > > +long virtio_media_device_ioctl(struct file *file, unsigned int cmd,
> > > + unsigned long arg);
> > > +extern const struct v4l2_ioctl_ops virtio_media_ioctl_ops;
> > > +
> > > +#endif // __VIRTIO_MEDIA_H
> > > --
> > > 2.55.0.rc0.799.gd6f94ed593-goog
> >
^ permalink raw reply
* Re: [PATCH v4 6/8] media: virtio: Add virtio_media_driver
From: Michael S. Tsirkin @ 2026-07-18 17:28 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Brian Daniels, Mauro Carvalho Chehab, acourbot, adelva, aesteve,
changyeon, daniel.almeida, eperezma, gnurou, gurchetansingh,
hverkuil, jasowang, linux-kernel, linux-media, nicolas.dufresne,
virtualization, xuanzhuo
In-Reply-To: <20260712085726.19198fda@foz.lan>
On Sun, Jul 12, 2026 at 08:57:26AM +0200, Mauro Carvalho Chehab wrote:
> On Thu, 25 Jun 2026 16:18:48 -0400
> Brian Daniels <briandaniels@google.com> wrote:
>
> > > > From: Alexandre Courbot <gnurou@gmail.com>
> > > >
> > > > virtio_media_driver.c provides the expected driver hooks, and support
> > > > for mmapping and polling.
> > > >
> > > > Signed-off-by: Alexandre Courbot <gnurou@gmail.com>
> > > > Co-developed-by: Brian Daniels <briandaniels@google.com>
> > > > Signed-off-by: Brian Daniels <briandaniels@google.com>
> > > > ---
> > > > drivers/media/virtio/virtio_media_driver.c | 959 +++++++++++++++++++++
> > > > 1 file changed, 959 insertions(+)
> > > > create mode 100644 drivers/media/virtio/virtio_media_driver.c
> > > >
> > > > diff --git a/drivers/media/virtio/virtio_media_driver.c b/drivers/media/virtio/virtio_media_driver.c
> > > > new file mode 100644
> > > > index 000000000..d6363c673
> > > > --- /dev/null
> > > > +++ b/drivers/media/virtio/virtio_media_driver.c
> > > > @@ -0,0 +1,959 @@
> > > > +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+
> > > > +
> > > > +/*
> > > > + * Virtio-media driver.
> > > > + *
> > > > + * Copyright (c) 2024-2025 Google LLC.
> > > > + */
> > > > +
> > > > +#include <linux/delay.h>
> > > > +#include <linux/device.h>
> > > > +#include <linux/dev_printk.h>
> > > > +#include <linux/mm.h>
> > > > +#include <linux/mutex.h>
> > > > +#include <linux/scatterlist.h>
> > > > +#include <linux/types.h>
> > > > +#include <linux/videodev2.h>
> > > > +#include <linux/vmalloc.h>
> > > > +#include <linux/wait.h>
> > > > +#include <linux/workqueue.h>
> > > > +#include <linux/module.h>
> > > > +#include <linux/moduleparam.h>
> > > > +#include <linux/virtio.h>
> > > > +#include <linux/virtio_config.h>
> > > > +#include <linux/virtio_ids.h>
> > > > +
> > > > +#include <media/frame_vector.h>
> > > > +#include <media/v4l2-dev.h>
> > > > +#include <media/v4l2-event.h>
> > > > +#include <media/videobuf2-memops.h>
> > > > +#include <media/v4l2-device.h>
> > > > +#include <media/v4l2-ioctl.h>
> > > > +
> > > > +#include "protocol.h"
> > > > +#include "session.h"
> > > > +#include "virtio_media.h"
> > > > +
> > > > +#define VIRTIO_MEDIA_NUM_EVENT_BUFS 16
> > > > +
> > > > +/* ID of the SHM region into which MMAP buffer will be mapped. */
> > > > +#define VIRTIO_MEDIA_SHM_MMAP 0
> > > > +
> > > > +/*
> > > > + * Name of the driver to expose to user-space.
> > > > + *
> > > > + * This is configurable because v4l2-compliance has workarounds specific to
> > > > + * some drivers. When proxying these directly from the host, this allows it to
> > > > + * apply them as needed.
> > > > + */
> > > > +char *virtio_media_driver_name;
> > > > +module_param_named(driver_name, virtio_media_driver_name, charp, 0660);
> > >
> > >
> > > Um. What? Not how it should be handled.
> >
> > I can remove this module param. I didn't end up using this when compliance testing.
> > Instead, I patched v4l-utils:
> > https://lore.kernel.org/all/20260528163448.4031965-1-briandaniels@google.com/
> >
> > Let me know if you think the v4l-utils patch is a good approach, otherwise let
> > me know how you'd prefer to address the v4l2-compliance driver-specific workounds
> > when they're being proxied with virtio-media.
>
> This kind of discussion should happen on a separate PR for v4l2-compliance,
> c/c to the proper developers and maintainers of it.
I wonder how migration can work when guest is tied to host driver model like
this.
> >
> > > > +
> > > > +/*
> > > > + * Whether USERPTR buffers are allowed.
> > > > + *
> > > > + * This is disabled by default as USERPTR buffers are dangerous, but the option
> > > > + * is left to enable them if desired.
> > > > + */
> > > > +bool virtio_media_allow_userptr;
> > > > +module_param_named(allow_userptr, virtio_media_allow_userptr, bool, 0660);
> > >
> > >
> > > is this kind of thing common?
>
> There is one old media device that has it (saa7134).
>
> >
> > To be honest, I don't really know. I'm also not that familiar with the USERPTR
> > issues. I see a few references online about their use being discouraged due to
> > possible race conditions, perhaps that was the original motivation for this
> > parameter (I'm not the original author of this driver).
> >
> > I'm open to alternatives, feel free to let me know if you have a preference.
>
> We tend to not implement USERPTR on newer drivers. I suggest you
> to place the logic with regards to V4L2_MEMORY_USERPTR on a separate
> patch for further discussions.
>
> >
> > > > +
> > > > +/**
> > > > + * virtio_media_session_alloc - Allocate a new session.
> > > > + * @vv: virtio-media device the session belongs to.
> > > > + * @id: ID of the session.
> > > > + * @nonblocking_dequeue: whether dequeuing of buffers should be blocking or
> > > > + * not.
> > > > + *
> > > > + * The ``id`` and ``list`` fields must still be set by the caller.
> > >
> > > still in what sense?
> >
> > Based on the code below, I'm not so sure that the caller is responsible for
> > setting these values. They seem to be initialized in the function.
> >
> > Perhaps Alexandre Courbot (the original author) would know more. Unless he
> > says otherwise though I'm inclined to remove this comment.
> >
> > > > + */
> > > > +static struct virtio_media_session *
> > > > +virtio_media_session_alloc(struct virtio_media *vv, u32 id,
> > > > + struct file *file)
> > > > +{
> > > > + struct virtio_media_session *session;
> > > > + int i;
> > > > + int ret;
> > > > +
> > > > + session = kzalloc_obj(*session, GFP_KERNEL);
> > > > + if (!session)
> > > > + goto err_session;
> > > > +
> > > > + session->shadow_buf = kzalloc(VIRTIO_SHADOW_BUF_SIZE, GFP_KERNEL);
> > > > + if (!session->shadow_buf)
> > > > + goto err_shadow_buf;
> > > > +
> > > > + ret = sg_alloc_table(&session->command_sgs, DESC_CHAIN_MAX_LEN,
> > > > + GFP_KERNEL);
> > > > + if (ret)
> > > > + goto err_payload_sgs;
> > > > +
> > > > + session->id = id;
> > > > + session->nonblocking_dequeue = file->f_flags & O_NONBLOCK;
> > > > +
> > > > + INIT_LIST_HEAD(&session->list);
> > > > + v4l2_fh_init(&session->fh, &vv->video_dev);
> > > > + virtio_media_session_fh_add(session, file);
> > > > +
> > > > + for (i = 0; i <= VIRTIO_MEDIA_LAST_QUEUE; i++)
> > > > + INIT_LIST_HEAD(&session->queues[i].pending_dqbufs);
> > > > + mutex_init(&session->queues_lock);
> > > > +
> > > > + init_waitqueue_head(&session->dqbuf_wait);
> > > > +
> > > > + mutex_lock(&vv->sessions_lock);
> > > > + list_add_tail(&session->list, &vv->sessions);
> > > > + mutex_unlock(&vv->sessions_lock);
> > > > +
> > > > + return session;
> > > > +
> > > > +err_payload_sgs:
> > > > + kfree(session->shadow_buf);
> > > > +err_shadow_buf:
> > > > + kfree(session);
> > > > +err_session:
> > > > + return ERR_PTR(-ENOMEM);
> > > > +}
> > > > +
> > > > +/**
> > > > + * virtio_media_session_free - Free all resources of a session.
> > > > + * @vv: virtio-media device the session belongs to.
> > > > + * @session: session to destroy.
> > > > + *
> > > > + * All the resources of @sesssion, as well as the backing memory of @session
> > > > + * itself, are freed.
> > >
> > > why @ here and `` above? And typo in the name.
> >
> > The `@` here was an attempt to follow the guide here for referencing function
> > parameters:
> > https://docs.kernel.org/doc-guide/kernel-doc.html#highlights-and-cross-references
>
> Yes. This is part of Linux Kernel kernel-doc markup: when referring to
> struct fields, you should use @field (or ``field`` if one wants to place an
> asterisk on it, like ``*field``).
>
> >
> > That being said, I don't believe this file is 100% consistent with that. I will
> > spend some time cleaning up the comments throughout this patch set to get them
> > consistent for v5. Thanks!
>
> Please use it on a consistent way along the driver.
>
>
> Thanks,
> Mauro
^ permalink raw reply
* Re: [PATCH v4 6/8] media: virtio: Add virtio_media_driver
From: Michael S. Tsirkin @ 2026-07-18 17:30 UTC (permalink / raw)
To: Brian Daniels
Cc: Mauro Carvalho Chehab, acourbot, adelva, aesteve, changyeon,
daniel.almeida, eperezma, gnurou, gurchetansingh, hverkuil,
jasowang, linux-kernel, linux-media, nicolas.dufresne,
virtualization, xuanzhuo
In-Reply-To: <20260625201850.2981130-1-briandaniels@google.com>
On Thu, Jun 25, 2026 at 04:18:48PM -0400, Brian Daniels wrote:
> > > From: Alexandre Courbot <gnurou@gmail.com>
> > >
> > > virtio_media_driver.c provides the expected driver hooks, and support
> > > for mmapping and polling.
> > >
> > > Signed-off-by: Alexandre Courbot <gnurou@gmail.com>
> > > Co-developed-by: Brian Daniels <briandaniels@google.com>
> > > Signed-off-by: Brian Daniels <briandaniels@google.com>
> > > ---
> > > drivers/media/virtio/virtio_media_driver.c | 959 +++++++++++++++++++++
> > > 1 file changed, 959 insertions(+)
> > > create mode 100644 drivers/media/virtio/virtio_media_driver.c
> > >
> > > diff --git a/drivers/media/virtio/virtio_media_driver.c b/drivers/media/virtio/virtio_media_driver.c
> > > new file mode 100644
> > > index 000000000..d6363c673
> > > --- /dev/null
> > > +++ b/drivers/media/virtio/virtio_media_driver.c
> > > @@ -0,0 +1,959 @@
> > > +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0+
> > > +
> > > +/*
> > > + * Virtio-media driver.
> > > + *
> > > + * Copyright (c) 2024-2025 Google LLC.
> > > + */
> > > +
> > > +#include <linux/delay.h>
> > > +#include <linux/device.h>
> > > +#include <linux/dev_printk.h>
> > > +#include <linux/mm.h>
> > > +#include <linux/mutex.h>
> > > +#include <linux/scatterlist.h>
> > > +#include <linux/types.h>
> > > +#include <linux/videodev2.h>
> > > +#include <linux/vmalloc.h>
> > > +#include <linux/wait.h>
> > > +#include <linux/workqueue.h>
> > > +#include <linux/module.h>
> > > +#include <linux/moduleparam.h>
> > > +#include <linux/virtio.h>
> > > +#include <linux/virtio_config.h>
> > > +#include <linux/virtio_ids.h>
> > > +
> > > +#include <media/frame_vector.h>
> > > +#include <media/v4l2-dev.h>
> > > +#include <media/v4l2-event.h>
> > > +#include <media/videobuf2-memops.h>
> > > +#include <media/v4l2-device.h>
> > > +#include <media/v4l2-ioctl.h>
> > > +
> > > +#include "protocol.h"
> > > +#include "session.h"
> > > +#include "virtio_media.h"
> > > +
> > > +#define VIRTIO_MEDIA_NUM_EVENT_BUFS 16
> > > +
> > > +/* ID of the SHM region into which MMAP buffer will be mapped. */
> > > +#define VIRTIO_MEDIA_SHM_MMAP 0
> > > +
> > > +/*
> > > + * Name of the driver to expose to user-space.
> > > + *
> > > + * This is configurable because v4l2-compliance has workarounds specific to
> > > + * some drivers. When proxying these directly from the host, this allows it to
> > > + * apply them as needed.
> > > + */
> > > +char *virtio_media_driver_name;
> > > +module_param_named(driver_name, virtio_media_driver_name, charp, 0660);
> >
> >
> > Um. What? Not how it should be handled.
>
> I can remove this module param. I didn't end up using this when compliance testing.
> Instead, I patched v4l-utils:
> https://lore.kernel.org/all/20260528163448.4031965-1-briandaniels@google.com/
>
> Let me know if you think the v4l-utils patch is a good approach, otherwise let
> me know how you'd prefer to address the v4l2-compliance driver-specific workounds
> when they're being proxied with virtio-media.
>
> > > +
> > > +/*
> > > + * Whether USERPTR buffers are allowed.
> > > + *
> > > + * This is disabled by default as USERPTR buffers are dangerous, but the option
> > > + * is left to enable them if desired.
> > > + */
> > > +bool virtio_media_allow_userptr;
> > > +module_param_named(allow_userptr, virtio_media_allow_userptr, bool, 0660);
> >
> >
> > is this kind of thing common?
>
> To be honest, I don't really know. I'm also not that familiar with the USERPTR
> issues. I see a few references online about their use being discouraged due to
> possible race conditions, perhaps that was the original motivation for this
> parameter (I'm not the original author of this driver).
>
> I'm open to alternatives, feel free to let me know if you have a preference.
>
> > > +
> > > +/**
> > > + * virtio_media_session_alloc - Allocate a new session.
> > > + * @vv: virtio-media device the session belongs to.
> > > + * @id: ID of the session.
> > > + * @nonblocking_dequeue: whether dequeuing of buffers should be blocking or
> > > + * not.
> > > + *
> > > + * The ``id`` and ``list`` fields must still be set by the caller.
> >
> > still in what sense?
>
> Based on the code below, I'm not so sure that the caller is responsible for
> setting these values. They seem to be initialized in the function.
>
> Perhaps Alexandre Courbot (the original author) would know more. Unless he
> says otherwise though I'm inclined to remove this comment.
>
> > > + */
> > > +static struct virtio_media_session *
> > > +virtio_media_session_alloc(struct virtio_media *vv, u32 id,
> > > + struct file *file)
> > > +{
> > > + struct virtio_media_session *session;
> > > + int i;
> > > + int ret;
> > > +
> > > + session = kzalloc_obj(*session, GFP_KERNEL);
> > > + if (!session)
> > > + goto err_session;
> > > +
> > > + session->shadow_buf = kzalloc(VIRTIO_SHADOW_BUF_SIZE, GFP_KERNEL);
> > > + if (!session->shadow_buf)
> > > + goto err_shadow_buf;
> > > +
> > > + ret = sg_alloc_table(&session->command_sgs, DESC_CHAIN_MAX_LEN,
> > > + GFP_KERNEL);
> > > + if (ret)
> > > + goto err_payload_sgs;
> > > +
> > > + session->id = id;
> > > + session->nonblocking_dequeue = file->f_flags & O_NONBLOCK;
> > > +
> > > + INIT_LIST_HEAD(&session->list);
> > > + v4l2_fh_init(&session->fh, &vv->video_dev);
> > > + virtio_media_session_fh_add(session, file);
> > > +
> > > + for (i = 0; i <= VIRTIO_MEDIA_LAST_QUEUE; i++)
> > > + INIT_LIST_HEAD(&session->queues[i].pending_dqbufs);
> > > + mutex_init(&session->queues_lock);
> > > +
> > > + init_waitqueue_head(&session->dqbuf_wait);
> > > +
> > > + mutex_lock(&vv->sessions_lock);
> > > + list_add_tail(&session->list, &vv->sessions);
> > > + mutex_unlock(&vv->sessions_lock);
> > > +
> > > + return session;
> > > +
> > > +err_payload_sgs:
> > > + kfree(session->shadow_buf);
> > > +err_shadow_buf:
> > > + kfree(session);
> > > +err_session:
> > > + return ERR_PTR(-ENOMEM);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_session_free - Free all resources of a session.
> > > + * @vv: virtio-media device the session belongs to.
> > > + * @session: session to destroy.
> > > + *
> > > + * All the resources of @sesssion, as well as the backing memory of @session
> > > + * itself, are freed.
> >
> > why @ here and `` above? And typo in the name.
>
> The `@` here was an attempt to follow the guide here for referencing function
> parameters:
> https://docs.kernel.org/doc-guide/kernel-doc.html#highlights-and-cross-references
>
> That being said, I don't believe this file is 100% consistent with that. I will
> spend some time cleaning up the comments throughout this patch set to get them
> consistent for v5. Thanks!
>
> > > + */
> > > +static void virtio_media_session_free(struct virtio_media *vv,
> > > + struct virtio_media_session *session)
> > > +{
> > > + int i;
> > > +
> > > + mutex_lock(&vv->sessions_lock);
> > > + list_del(&session->list);
> > > + mutex_unlock(&vv->sessions_lock);
> > > +
> > > + virtio_media_session_fh_del(session);
> > > + v4l2_fh_exit(&session->fh);
> > > +
> > > + sg_free_table(&session->command_sgs);
> > > +
> > > + for (i = 0; i <= VIRTIO_MEDIA_LAST_QUEUE; i++)
> > > + vfree(session->queues[i].buffers);
> > > +
> > > + kfree(session->shadow_buf);
> > > + kfree(session);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_session_close - Close and free a session.
> > > + * @vv: virtio-media device the session belongs to.
> > > + * @session: session to close and destroy.
> > > + *
> > > + * This send the ``VIRTIO_MEDIA_CMD_CLOSE`` command to the device, and frees
> >
> > sends
>
> Fix staged in v5
>
> > > + * all resources used by @session.
> > > + */
> > > +static int virtio_media_session_close(struct virtio_media *vv,
> > > + struct virtio_media_session *session)
> > > +{
> > > + struct virtio_media_cmd_close *cmd_close = &session->cmd.close;
> > > + struct scatterlist cmd_sg = {};
> > > + struct scatterlist *sgs[1] = { &cmd_sg };
> > > + int ret;
> > > +
> > > + mutex_lock(&vv->vlock);
> > > +
> > > + cmd_close->hdr.cmd = VIRTIO_MEDIA_CMD_CLOSE;
> > > + cmd_close->session_id = session->id;
> > > +
> > > + sg_set_buf(&cmd_sg, cmd_close, sizeof(*cmd_close));
> > > + sg_mark_end(&cmd_sg);
> > > +
> > > + ret = virtio_media_send_command(vv, sgs, 1, 0, 0, NULL);
> > > + mutex_unlock(&vv->vlock);
> > > + if (ret < 0)
> > > + return ret;
> > > +
> > > + virtio_media_session_free(vv, session);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_find_session - Lookup for the session with a given ID.
> >
> > a session
>
> Fix staged in v5
>
> > > + * @vv: virtio-media device to lookup the session from.
> > > + * @id: ID of the session to lookup.
> > > + */
> > > +static struct virtio_media_session *
> > > +virtio_media_find_session(struct virtio_media *vv, u32 id)
> > > +{
> > > + struct list_head *p;
> > > + struct virtio_media_session *session = NULL;
> > > +
> > > + mutex_lock(&vv->sessions_lock);
> > > + list_for_each(p, &vv->sessions) {
> > > + struct virtio_media_session *s =
> > > + list_entry(p, struct virtio_media_session, list);
> > > + if (s->id == id) {
> > > + session = s;
> > > + break;
> > > + }
> > > + }
> > > + mutex_unlock(&vv->sessions_lock);
> > > +
> > > + return session;
> > > +}
> > > +
> > > +/**
> > > + * struct virtio_media_cmd_callback_param - Callback parameters to the virtio
> > > + * command queue.
> > > + * @vv: virtio-media device in use.
> > > + * @done: flag to be switched once the command is completed.
> > > + * @resp_len: length of the received response from the command. Only valid
> > > + * after @done_flag has switched to ``true``.
> >
> > confusing indent
>
> Fix staged in v5
>
> > > + */
> > > +struct virtio_media_cmd_callback_param {
> > > + struct virtio_media *vv;
> > > + bool done;
> > > + size_t resp_len;
> > > +};
> > > +
> > > +/**
> > > + * commandq_callback: Callback for the command queue.
> > > + * @queue: command virtqueue.
> > > + *
> > > + * This just wakes up the thread that was waiting on the command to complete.
> > > + */
> > > +static void commandq_callback(struct virtqueue *queue)
> > > +{
> > > + unsigned int len;
> > > + struct virtio_media_cmd_callback_param *param;
> > > +
> > > +process_bufs:
> > > + while ((param = virtqueue_get_buf(queue, &len))) {
> > > + param->done = true;
> > > + param->resp_len = len;
> > > + wake_up(¶m->vv->wq);
> > > + }
> > > +
> > > + if (!virtqueue_enable_cb(queue)) {
> > > + virtqueue_disable_cb(queue);
> > > + goto process_bufs;
> > > + }
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_kick_command - send a command to the commandq.
> > > + * @vv: virtio-media device in use.
> > > + * @sgs: descriptor chain to send.
> > > + * @out_sgs: number of device-readable descriptors in @sgs.
> > > + * @in_sgs: number of device-writable descriptors in @sgs.
> > > + * @resp_len: output parameter. Upon success, contains the size of the response
> > > + * in bytes.
> >
> > confusing indent
> >
> > > + *
> >
> > why an empty line?
>
> Indent fixed and empty line removed in v5
>
> > > + */
> > > +static int virtio_media_kick_command(struct virtio_media *vv,
> > > + struct scatterlist **sgs,
> > > + const size_t out_sgs, const size_t in_sgs,
> > > + size_t *resp_len)
> > > +{
> > > + struct virtio_media_cmd_callback_param cb_param = {
> > > + .vv = vv,
> > > + .done = false,
> > > + .resp_len = 0,
> > > + };
> > > + struct virtio_media_resp_header *resp_header;
> > > + int ret;
> > > +
> > > + ret = virtqueue_add_sgs(vv->commandq, sgs, out_sgs, in_sgs, &cb_param,
> > > + GFP_ATOMIC);
> >
> >
> > can init with declaration.
>
> Thanks, added to v5
>
> > > + if (ret) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "failed to add sgs to command virtqueue\n");
> > > + return ret;
> > > + }
> > > +
> > > + if (!virtqueue_kick(vv->commandq)) {
> > > + v4l2_err(&vv->v4l2_dev, "failed to kick command virtqueue\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + /* Wait for the response. */
> > > + ret = wait_event_timeout(vv->wq, cb_param.done, 5 * HZ);
> > > + if (ret == 0) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "timed out waiting for response to command\n");
> > > + return -ETIMEDOUT;
> > > + }
> > > +
> > > + if (resp_len)
> > > + *resp_len = cb_param.resp_len;
> > > +
> > > + if (in_sgs > 0) {
> > > + /*
> > > + * If we expect a response, make sure we have at least a
> > > + * response header - anything shorter is invalid.
> > > + */
> > > + if (cb_param.resp_len < sizeof(*resp_header)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "received response header is too short\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + resp_header = sg_virt(sgs[out_sgs]);
> > > + if (resp_header->status)
> > > + /* Host returns a positive error code. */
> > > + return -resp_header->status;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_send_command - Send a command to the device and wait for its
> > > + * response.
> > > + * @vv: virtio-media device in use.
> > > + * @sgs: descriptor chain to send.
> > > + * @out_sgs: number of device-readable descriptors in @sgs.
> > > + * @in_sgs: number of device-writable descriptors in @sgs.
> > > + * @minimum_resp_len: minimum length of the response expected by the caller
> > > + * when the command is successful. Anything shorter than that will result in
> > > + * ``-EINVAL`` being returned.
> > > + * @resp_len: output parameter. Upon success, contains the size of the response
> > > + * in bytes.
> > > + */
> > > +int virtio_media_send_command(struct virtio_media *vv, struct scatterlist **sgs,
> > > + const size_t out_sgs, const size_t in_sgs,
> > > + size_t minimum_resp_len, size_t *resp_len)
> > > +{
> > > + size_t local_resp_len = resp_len ? *resp_len : 0;
> > > + int ret = virtio_media_kick_command(vv, sgs, out_sgs, in_sgs,
> > > + &local_resp_len);
> > > + if (resp_len)
> > > + *resp_len = local_resp_len;
> > > +
> > > + /*
> > > + * If the host could not process the command, there is no valid
> > > + * response.
> > > + */
> > > + if (ret < 0)
> > > + return ret;
> > > +
> > > + /* Make sure the host wrote a complete reply. */
> > > + if (local_resp_len < minimum_resp_len) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "received response is too short: received %zu, expected at least %zu\n",
> > > + local_resp_len, minimum_resp_len);
> > > + return -EINVAL;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_send_event_buffer() - Sends an event buffer to the host so it
> > > + * can return it with an event.
> > > + * @vv: virtio-media device in use.
> > > + * @event_buffer: pointer to the event buffer to send to the device.
> > > + */
> > > +static int virtio_media_send_event_buffer(struct virtio_media *vv,
> > > + void *event_buffer)
> > > +{
> > > + struct scatterlist *sgs[1], vresp;
> > > + int ret;
> > > +
> > > + sg_init_one(&vresp, event_buffer, VIRTIO_MEDIA_EVENT_MAX_SIZE);
> > > + sgs[0] = &vresp;
> >
> > what is this convoluted thing? why not pass &vresp directly?
>
> `virtqueue_add_sgs` expects a `struct scatterlist **`. Passing `&vresp` is
> only a single pointer and it needs a double pointer.
>
> It could be written as:
>
> struct scatterlist *sgs, vresp;
>
> sg_init_one(&vresp, event_buffer, VIRTIO_MEDIA_EVENT_MAX_SIZE);
> sgs = &vresp;
> ret = virtqueue_add_sgs(vv->eventq, &sgs, 0, 1, event_buffer,
>
> But I suspect it's written as is to match `virtqueue_add_sgs`'s function
> declaration:
>
> int virtqueue_add_sgs(struct virtqueue *vq,
> struct scatterlist *sgs[],
> unsigned int out_sgs,
> unsigned int in_sgs,
> void *data,
> gfp_t gfp);
>
> > > +
> > > + ret = virtqueue_add_sgs(vv->eventq, sgs, 0, 1, event_buffer,
> > > + GFP_ATOMIC);
> >
> >
> > This does not work uness event_buffer is aligned for dma.
> > But it does not seem to be:
> >
> > for (i = 0; i < VIRTIO_MEDIA_NUM_EVENT_BUFS; i++) {
> > void *ebuf = vv->event_buffer + VIRTIO_MEDIA_EVENT_MAX_SIZE * i;
> >
> > ret = virtio_media_send_event_buffer(vv, ebuf);
> > if (ret)
> > goto err_send_event_buffer;
>
> Apologies if the following questions are bit basic, I'm still pretty new to
> this.
>
> Is the dma alignment requirement a general requirement for calling the
> `virtqueue_add_sgs` function? Or is the dma alignment requirement to allow the
> driver to support DMABUF transfers? If its the later, I should note this driver
> does not support DMABUF transfers yet when streaming frames.
>
> If it's the former, then how would I go about ensuring its dma aligned?
See Documentation/core-api/dma-api-howto.rst
> >From the code block you quoted above, `vv->event_buffer` is allocated like so:
>
> vv->event_buffer = devm_kzalloc(dev,
> VIRTIO_MEDIA_EVENT_MAX_SIZE *
> VIRTIO_MEDIA_NUM_EVENT_BUFS,
> GFP_KERNEL);
> if (!vv->event_buffer)
> return -ENOMEM;
>
> Do I need to call something else besides `devm_kzalloc()` to ensure every
> element within the vv->event_buffer array is dma aligned?
You need to either allocate each one separately or
add padding.
> >
> >
> > > + if (ret) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "failed to add sgs to event virtqueue\n");
> > > + return ret;
> > > + }
> > > +
> > > + if (!virtqueue_kick(vv->eventq)) {
> > > + v4l2_err(&vv->v4l2_dev, "failed to kick event virtqueue\n");
> > > + return -EINVAL;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * eventq_callback() - Callback for the event queue.
> > > + * @queue: event virtqueue.
> > > + *
> > > + * This just schedules for event work to be run.
> > > + */
> > > +static void eventq_callback(struct virtqueue *queue)
> > > +{
> > > + struct virtio_media *vv = queue->vdev->priv;
> > > +
> > > + schedule_work(&vv->eventq_work);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_process_dqbuf_event() - Process a dequeued event for a session.
> > > + * @vv: virtio-media device in use.
> > > + * @session: session the event is addressed to.
> > > + * @dqbuf_evt: the dequeued event to process.
> > > + *
> > > + * Invalid events are ignored with an error log.
> > > + */
> > > +static void
> > > +virtio_media_process_dqbuf_event(struct virtio_media *vv,
> > > + struct virtio_media_session *session,
> > > + struct virtio_media_event_dqbuf *dqbuf_evt)
> > > +{
> > > + struct virtio_media_buffer *dqbuf;
> > > + const enum v4l2_buf_type queue_type = dqbuf_evt->buffer.type;
> > > + struct virtio_media_queue_state *queue;
> > > + typeof(dqbuf->buffer.m) buffer_m;
> > > + typeof(dqbuf->buffer.m.planes[0].m) plane_m;
> > > + int i;
> > > +
> > > + if (queue_type >= ARRAY_SIZE(session->queues)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "unmanaged queue %d passed to dqbuf event",
> > > + dqbuf_evt->buffer.type);
> > > + return;
> > > + }
> > > + queue = &session->queues[queue_type];
> > > +
> > > + if (dqbuf_evt->buffer.index >= queue->allocated_bufs) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "invalid buffer ID %d for queue %d in dqbuf event",
> > > + dqbuf_evt->buffer.index, dqbuf_evt->buffer.type);
> > > + return;
> > > + }
> > > +
> > > + dqbuf = &queue->buffers[dqbuf_evt->buffer.index];
> > > +
> > > + /*
> > > + * Preserve the 'm' union that was passed to us during QBUF so userspace
> > > + * gets back the information it submitted.
> > > + */
> > > + buffer_m = dqbuf->buffer.m;
> > > + memcpy(&dqbuf->buffer, &dqbuf_evt->buffer, sizeof(dqbuf->buffer));
> > > + dqbuf->buffer.m = buffer_m;
> > > + if (V4L2_TYPE_IS_MULTIPLANAR(dqbuf->buffer.type)) {
> > > + if (dqbuf->buffer.length > VIDEO_MAX_PLANES) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "invalid number of planes received from host for a multiplanar buffer\n");
> > > + return;
> > > + }
> > > + for (i = 0; i < dqbuf->buffer.length; i++) {
> > > + plane_m = dqbuf->planes[i].m;
> > > + memcpy(&dqbuf->planes[i], &dqbuf_evt->planes[i],
> > > + sizeof(struct v4l2_plane));
> > > + dqbuf->planes[i].m = plane_m;
> > > + }
> > > + }
> > > +
> > > + /* Set the DONE flag as the buffer is waiting for being dequeued. */
> > > + dqbuf->buffer.flags |= V4L2_BUF_FLAG_DONE;
> > > +
> > > + mutex_lock(&session->queues_lock);
> > > + list_add_tail(&dqbuf->list, &queue->pending_dqbufs);
> > > + queue->queued_bufs -= 1;
> > > + mutex_unlock(&session->queues_lock);
> > > +
> > > + wake_up(&session->dqbuf_wait);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_process_events() - Process all pending events on a device.
> > > + * @vv: device which pending events we want to process.
> > > + *
> > > + * Retrieves all pending events on @vv's event queue and dispatch them to their
> > > + * corresponding session.
> > > + *
> > > + * Invalid events are ignored with an error log.
> > > + */
> > > +void virtio_media_process_events(struct virtio_media *vv)
> > > +{
> > > + struct virtio_media_event_error *error_evt;
> > > + struct virtio_media_event_dqbuf *dqbuf_evt;
> > > + struct virtio_media_event_event *event_evt;
> > > + struct virtio_media_session *session;
> > > + struct virtio_media_event_header *evt;
> > > + unsigned int len;
> > > +
> > > + mutex_lock(&vv->events_lock);
> > > +
> > > +process_bufs:
> > > + while ((evt = virtqueue_get_buf(vv->eventq, &len))) {
> > > + /* Make sure we received enough data */
> > > + if (len < sizeof(*evt)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "event is too short: got %u, expected at least %zu\n",
> > > + len, sizeof(*evt));
> > > + goto end_of_event;
> > > + }
> > > +
> > > + session = virtio_media_find_session(vv, evt->session_id);
> > > + if (!session) {
> > > + v4l2_err(&vv->v4l2_dev, "cannot find session %d\n",
> > > + evt->session_id);
> > > + goto end_of_event;
> > > + }
> > > +
> > > + switch (evt->event) {
> > > + case VIRTIO_MEDIA_EVT_ERROR:
> > > + if (len < sizeof(*error_evt)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "error event is too short: got %u, expected %zu\n",
> > > + len, sizeof(*error_evt));
> > > + break;
> > > + }
> > > + error_evt = (struct virtio_media_event_error *)evt;
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "received error %d for session %d",
> > > + error_evt->errno, error_evt->hdr.session_id);
> > > + virtio_media_session_close(vv, session);
> > > + break;
> > > +
> > > + /*
> > > + * Dequeued buffer: put it into the right queue so user-space
> > > + * can dequeue it.
> > > + */
> > > + case VIRTIO_MEDIA_EVT_DQBUF:
> > > + if (len < sizeof(*dqbuf_evt)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "dqbuf event is too short: got %u, expected %zu\n",
> > > + len, sizeof(*dqbuf_evt));
> > > + break;
> > > + }
> > > + dqbuf_evt = (struct virtio_media_event_dqbuf *)evt;
> > > + virtio_media_process_dqbuf_event(vv, session,
> > > + dqbuf_evt);
> > > + break;
> > > +
> > > + case VIRTIO_MEDIA_EVT_EVENT:
> > > + if (len < sizeof(*event_evt)) {
> > > + v4l2_err(&vv->v4l2_dev,
> > > + "session event is too short: got %u expected %zu\n",
> > > + len, sizeof(*event_evt));
> > > + break;
> > > + }
> > > +
> > > + event_evt = (struct virtio_media_event_event *)evt;
> > > + v4l2_event_queue_fh(&session->fh, &event_evt->event);
> > > + break;
> > > +
> > > + default:
> > > + v4l2_err(&vv->v4l2_dev, "unknown event type %d\n",
> > > + evt->event);
> > > + break;
> > > + }
> > > +
> > > +end_of_event:
> > > + virtio_media_send_event_buffer(vv, evt);
> > > + }
> > > +
> > > + if (!virtqueue_enable_cb(vv->eventq)) {
> > > + virtqueue_disable_cb(vv->eventq);
> > > + goto process_bufs;
> > > + }
> > > +
> > > + mutex_unlock(&vv->events_lock);
> > > +}
> > > +
> > > +static void virtio_media_event_work(struct work_struct *work)
> > > +{
> > > + struct virtio_media *vv =
> > > + container_of(work, struct virtio_media, eventq_work);
> > > +
> > > + virtio_media_process_events(vv);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_device_open() - Create a new session from an opened file.
> > > + * @file: opened file for the session.
> > > + */
> > > +static int virtio_media_device_open(struct file *file)
> > > +{
> > > + struct video_device *video_dev = video_devdata(file);
> > > + struct virtio_media *vv = to_virtio_media(video_dev);
> > > + struct virtio_media_cmd_open *cmd_open = &vv->cmd.open;
> > > + struct virtio_media_resp_open *resp_open = &vv->resp.open;
> > > + struct scatterlist cmd_sg = {}, resp_sg = {};
> > > + struct scatterlist *sgs[2] = { &cmd_sg, &resp_sg };
> > > + struct virtio_media_session *session;
> > > + u32 session_id;
> > > + int ret;
> > > +
> > > + mutex_lock(&vv->vlock);
> > > +
> > > + sg_set_buf(&cmd_sg, cmd_open, sizeof(*cmd_open));
> > > + sg_mark_end(&cmd_sg);
> > > +
> > > + sg_set_buf(&resp_sg, resp_open, sizeof(*resp_open));
> > > + sg_mark_end(&resp_sg);
> > > +
> > > + cmd_open->hdr.cmd = VIRTIO_MEDIA_CMD_OPEN;
> > > + ret = virtio_media_send_command(vv, sgs, 1, 1, sizeof(*resp_open),
> > > + NULL);
> > > + session_id = resp_open->session_id;
> > > + mutex_unlock(&vv->vlock);
> > > + if (ret < 0)
> > > + return ret;
> > > +
> > > + session = virtio_media_session_alloc(vv, session_id, file);
> > > + if (IS_ERR(session))
> > > + return PTR_ERR(session);
> > > +
> > > + file->private_data = &session->fh;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_device_close() - Close a previously opened session.
> > > + * @file: file of the session to close.
> > > + *
> > > + * This sends to ``VIRTIO_MEDIA_CMD_CLOSE`` command to the device, and close
> > > + * the session on the driver side.
> > > + */
> > > +static int virtio_media_device_close(struct file *file)
> > > +{
> > > + struct video_device *video_dev = video_devdata(file);
> > > + struct virtio_media *vv = to_virtio_media(video_dev);
> > > + struct virtio_media_session *session =
> > > + fh_to_session(file->private_data);
> > > +
> > > + return virtio_media_session_close(vv, session);
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_device_poll() - Poll logic for a virtio-media device.
> > > + * @file: file of the session to poll.
> > > + * @wait: poll table to wait on.
> > > + */
> > > +static __poll_t virtio_media_device_poll(struct file *file, poll_table *wait)
> > > +{
> > > + struct virtio_media_session *session =
> > > + fh_to_session(file->private_data);
> > > + enum v4l2_buf_type capture_type =
> > > + session->uses_mplane ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
> > > + V4L2_BUF_TYPE_VIDEO_CAPTURE;
> > > + enum v4l2_buf_type output_type =
> > > + session->uses_mplane ? V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
> > > + V4L2_BUF_TYPE_VIDEO_OUTPUT;
> > > + struct virtio_media_queue_state *capture_queue =
> > > + &session->queues[capture_type];
> > > + struct virtio_media_queue_state *output_queue =
> > > + &session->queues[output_type];
> > > + __poll_t req_events = poll_requested_events(wait);
> > > + __poll_t rc = 0;
> > > +
> > > + poll_wait(file, &session->dqbuf_wait, wait);
> > > + poll_wait(file, &session->fh.wait, wait);
> > > +
> > > + mutex_lock(&session->queues_lock);
> > > + if (req_events & (EPOLLIN | EPOLLRDNORM)) {
> > > + if (!capture_queue->streaming ||
> > > + (capture_queue->queued_bufs == 0 &&
> > > + list_empty(&capture_queue->pending_dqbufs)))
> > > + rc |= EPOLLERR;
> > > + else if (!list_empty(&capture_queue->pending_dqbufs))
> > > + rc |= EPOLLIN | EPOLLRDNORM;
> > > + }
> > > + if (req_events & (EPOLLOUT | EPOLLWRNORM)) {
> > > + if (!output_queue->streaming)
> > > + rc |= EPOLLERR;
> > > + else if (output_queue->queued_bufs <
> > > + output_queue->allocated_bufs)
> > > + rc |= EPOLLOUT | EPOLLWRNORM;
> > > + }
> > > + mutex_unlock(&session->queues_lock);
> > > +
> > > + if (v4l2_event_pending(&session->fh))
> > > + rc |= EPOLLPRI;
> > > +
> > > + return rc;
> > > +}
> > > +
> > > +static void virtio_media_vma_close_locked(struct vm_area_struct *vma)
> > > +{
> > > + struct virtio_media *vv = vma->vm_private_data;
> > > + struct virtio_media_cmd_munmap *cmd_munmap = &vv->cmd.munmap;
> > > + struct virtio_media_resp_munmap *resp_munmap = &vv->resp.munmap;
> > > + struct scatterlist cmd_sg = {}, resp_sg = {};
> > > + struct scatterlist *sgs[2] = { &cmd_sg, &resp_sg };
> > > + int ret;
> > > +
> > > + sg_set_buf(&cmd_sg, cmd_munmap, sizeof(*cmd_munmap));
> > > + sg_mark_end(&cmd_sg);
> > > +
> > > + sg_set_buf(&resp_sg, resp_munmap, sizeof(*resp_munmap));
> > > + sg_mark_end(&resp_sg);
> > > +
> > > + cmd_munmap->hdr.cmd = VIRTIO_MEDIA_CMD_MUNMAP;
> > > + cmd_munmap->driver_addr =
> > > + (vma->vm_pgoff << PAGE_SHIFT) - vv->mmap_region.addr;
> > > + ret = virtio_media_send_command(vv, sgs, 1, 1, sizeof(*resp_munmap),
> > > + NULL);
> > > + if (ret < 0) {
> > > + v4l2_err(&vv->v4l2_dev, "host failed to unmap buffer: %d\n",
> > > + ret);
> > > + }
> > > +}
> > > +
> > > +/**
> > > + * virtio_media_vma_close() - Close a MMAP buffer mapping.
> > > + * @vma: VMA of the mapping to close.
> > > + *
> > > + * Inform the host that a previously created MMAP mapping is no longer needed
> > > + * and can be removed.
> > > + */
> > > +static void virtio_media_vma_close(struct vm_area_struct *vma)
> > > +{
> > > + struct virtio_media *vv = vma->vm_private_data;
> > > +
> > > + mutex_lock(&vv->vlock);
> > > + virtio_media_vma_close_locked(vma);
> > > + mutex_unlock(&vv->vlock);
> > > +}
> > > +
> > > +static const struct vm_operations_struct virtio_media_vm_ops = {
> > > + .close = virtio_media_vma_close,
> > > +};
> > > +
> > > +/**
> > > + * virtio_media_device_mmap - Perform a mmap request from userspace.
> > > + * @file: opened file of the session to map for.
> > > + * @vma: VM area struct describing the desired mapping.
> > > + *
> > > + * This requests the host to map a MMAP buffer for us, so we can then make that
> > > + * mapping visible into user-space address space.
> > > + */
> > > +static int virtio_media_device_mmap(struct file *file,
> > > + struct vm_area_struct *vma)
> > > +{
> > > + struct video_device *video_dev = video_devdata(file);
> > > + struct virtio_media *vv = to_virtio_media(video_dev);
> > > + struct virtio_media_session *session =
> > > + fh_to_session(file->private_data);
> > > + struct virtio_media_cmd_mmap *cmd_mmap = &session->cmd.mmap;
> > > + struct virtio_media_resp_mmap *resp_mmap = &session->resp.mmap;
> > > + struct scatterlist cmd_sg = {}, resp_sg = {};
> > > + struct scatterlist *sgs[2] = { &cmd_sg, &resp_sg };
> > > + int ret;
> > > +
> > > + if (!(vma->vm_flags & VM_SHARED))
> > > + return -EINVAL;
> > > + if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
> > > + return -EINVAL;
> > > +
> > > + mutex_lock(&vv->vlock);
> > > +
> > > + cmd_mmap->hdr.cmd = VIRTIO_MEDIA_CMD_MMAP;
> > > + cmd_mmap->session_id = session->id;
> > > + cmd_mmap->flags =
> > > + (vma->vm_flags & VM_WRITE) ? VIRTIO_MEDIA_MMAP_FLAG_RW : 0;
> > > + cmd_mmap->offset = vma->vm_pgoff << PAGE_SHIFT;
> > > +
> > > + sg_set_buf(&cmd_sg, cmd_mmap, sizeof(*cmd_mmap));
> > > + sg_mark_end(&cmd_sg);
> > > +
> > > + sg_set_buf(&resp_sg, resp_mmap, sizeof(*resp_mmap));
> > > + sg_mark_end(&resp_sg);
> > > +
> > > + /*
> > > + * The host performs reference counting and is smart enough to return
> > > + * the same guest physical address if this is called several times on
> > > + * the same
> > > + * buffer.
> > > + */
> > > + ret = virtio_media_send_command(vv, sgs, 1, 1, sizeof(*resp_mmap),
> > > + NULL);
> > > + if (ret < 0)
> > > + goto end;
> > > +
> > > + vma->vm_private_data = vv;
> > > + /*
> > > + * Keep the guest address at which the buffer is mapped since we will
> > > + * use that to unmap.
> > > + */
> > > + vma->vm_pgoff = (resp_mmap->driver_addr + vv->mmap_region.addr) >>
> > > + PAGE_SHIFT;
> > > +
> > > + /*
> > > + * We cannot let the mapping be larger than the buffer.
> > > + */
> > > + if (vma->vm_end - vma->vm_start > PAGE_ALIGN(resp_mmap->len)) {
> > > + dev_dbg(&video_dev->dev,
> > > + "invalid MMAP, as it would overflow buffer length\n");
> > > + virtio_media_vma_close_locked(vma);
> > > + ret = -EINVAL;
> > > + goto end;
> > > + }
> > > +
> > > + ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
> > > + vma->vm_end - vma->vm_start,
> > > + vma->vm_page_prot);
> > > + if (ret)
> > > + goto end;
> > > +
> > > + vma->vm_ops = &virtio_media_vm_ops;
> > > +
> > > +end:
> > > + mutex_unlock(&vv->vlock);
> > > + return ret;
> > > +}
> > > +
> > > +static const struct v4l2_file_operations virtio_media_fops = {
> > > + .owner = THIS_MODULE,
> > > + .open = virtio_media_device_open,
> > > + .release = virtio_media_device_close,
> > > + .poll = virtio_media_device_poll,
> > > + .unlocked_ioctl = virtio_media_device_ioctl,
> > > + .mmap = virtio_media_device_mmap,
> > > +};
> > > +
> > > +static int virtio_media_probe(struct virtio_device *virtio_dev)
> > > +{
> > > + struct device *dev = &virtio_dev->dev;
> > > + struct virtqueue *vqs[2];
> > > + static struct virtqueue_info vq_info[2] = {
> > > + {
> > > + .name = "command",
> > > + .callback = commandq_callback,
> > > + },
> > > + {
> > > + .name = "event",
> > > + .callback = eventq_callback,
> > > + },
> > > + };
> > > + struct virtio_media *vv;
> > > + struct video_device *vd;
> > > + int i;
> > > + int ret;
> > > +
> > > + vv = devm_kzalloc(dev, sizeof(*vv), GFP_KERNEL);
> > > + if (!vv)
> > > + return -ENOMEM;
> > > +
> > > + vv->event_buffer = devm_kzalloc(dev,
> > > + VIRTIO_MEDIA_EVENT_MAX_SIZE *
> > > + VIRTIO_MEDIA_NUM_EVENT_BUFS,
> > > + GFP_KERNEL);
> > > + if (!vv->event_buffer)
> > > + return -ENOMEM;
> > > +
> > > + INIT_LIST_HEAD(&vv->sessions);
> > > + mutex_init(&vv->sessions_lock);
> > > + mutex_init(&vv->events_lock);
> > > + mutex_init(&vv->vlock);
> > > +
> > > + vv->virtio_dev = virtio_dev;
> > > + virtio_dev->priv = vv;
> > > +
> > > + init_waitqueue_head(&vv->wq);
> > > +
> > > + ret = v4l2_device_register(dev, &vv->v4l2_dev);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = virtio_find_vqs(virtio_dev, 2, vqs, vq_info, NULL);
> > > + if (ret)
> > > + goto err_find_vqs;
> > > +
> > > + vv->commandq = vqs[0];
> > > + vv->eventq = vqs[1];
> > > + INIT_WORK(&vv->eventq_work, virtio_media_event_work);
> > > +
> > > + /* Get MMAP buffer mapping SHM region */
> > > + virtio_get_shm_region(virtio_dev, &vv->mmap_region,
> > > + VIRTIO_MEDIA_SHM_MMAP);
> > > +
> > > + vd = &vv->video_dev;
> > > +
> > > + vd->v4l2_dev = &vv->v4l2_dev;
> > > + vd->vfl_type = VFL_TYPE_VIDEO;
> > > + vd->ioctl_ops = &virtio_media_ioctl_ops;
> > > + vd->fops = &virtio_media_fops;
> > > + vd->device_caps = virtio_cread32(virtio_dev, 0);
> > > + if (vd->device_caps & (V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE))
> > > + vd->vfl_dir = VFL_DIR_M2M;
> > > + else if (vd->device_caps &
> > > + (V4L2_CAP_VIDEO_OUTPUT | V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE))
> > > + vd->vfl_dir = VFL_DIR_TX;
> > > + else
> > > + vd->vfl_dir = VFL_DIR_RX;
> > > + vd->release = video_device_release_empty;
> > > + strscpy(vd->name, "virtio-media", sizeof(vd->name));
> > > +
> > > + video_set_drvdata(vd, vv);
> > > +
> > > + ret = video_register_device(vd, virtio_cread32(virtio_dev, 4), 0);
> > > + if (ret)
> > > + goto err_register_device;
> > > +
> > > + for (i = 0; i < VIRTIO_MEDIA_NUM_EVENT_BUFS; i++) {
> > > + void *ebuf = vv->event_buffer + VIRTIO_MEDIA_EVENT_MAX_SIZE * i;
> > > +
> > > + ret = virtio_media_send_event_buffer(vv, ebuf);
> > > + if (ret)
> > > + goto err_send_event_buffer;
> > > + }
> > > +
> > > + virtio_device_ready(virtio_dev);
> > > +
> > > + return 0;
> > > +
> > > +err_send_event_buffer:
> > > + video_unregister_device(&vv->video_dev);
> > > +err_register_device:
> > > + virtio_dev->config->del_vqs(virtio_dev);
> > > +err_find_vqs:
> > > + v4l2_device_unregister(&vv->v4l2_dev);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static void virtio_media_remove(struct virtio_device *virtio_dev)
> > > +{
> > > + struct virtio_media *vv = virtio_dev->priv;
> > > + struct list_head *p, *n;
> > > +
> > > + cancel_work_sync(&vv->eventq_work);
> > > + virtio_reset_device(virtio_dev);
> > > +
> > > + v4l2_device_unregister(&vv->v4l2_dev);
> > > + virtio_dev->config->del_vqs(virtio_dev);
> > > + video_unregister_device(&vv->video_dev);
> > > +
> > > + list_for_each_safe(p, n, &vv->sessions) {
> > > + struct virtio_media_session *s =
> > > + list_entry(p, struct virtio_media_session, list);
> > > +
> > > + virtio_media_session_free(vv, s);
> > > + }
> > > +}
> > > +
> > > +static struct virtio_device_id id_table[] = {
> > > + { VIRTIO_ID_MEDIA, VIRTIO_DEV_ANY_ID },
> > > + { 0 },
> > > +};
> > > +
> > > +static unsigned int features[] = {};
> > > +
> > > +static struct virtio_driver virtio_media_driver = {
> > > + .feature_table = features,
> > > + .feature_table_size = ARRAY_SIZE(features),
> > > + .driver.name = VIRTIO_MEDIA_DEFAULT_DRIVER_NAME,
> > > + .driver.owner = THIS_MODULE,
> > > + .id_table = id_table,
> > > + .probe = virtio_media_probe,
> > > + .remove = virtio_media_remove,
> > > +};
> > > +
> > > +module_virtio_driver(virtio_media_driver);
> > > +
> > > +MODULE_DEVICE_TABLE(virtio, id_table);
> > > +MODULE_DESCRIPTION("virtio media driver");
> > > +MODULE_AUTHOR("Alexandre Courbot <gnurou@gmail.com>");
> > > +MODULE_LICENSE("Dual BSD/GPL");
^ permalink raw reply
* Re: [PATCH v2 1/4] virtio-mem: validate device-reported block size
From: Carlos Bilbao @ 2026-07-18 17:41 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Greg Kroah-Hartman, David Hildenbrand (Arm), Hari Mishal,
Jason Wang, Xuan Zhuo, Eugenio Pérez, virtualization,
linux-kernel, elena.reshetova, huster, mhollick, jiska.classen
In-Reply-To: <20260718131715-mutt-send-email-mst@kernel.org>
Hello Michael,
On 7/18/26 10:21, Michael S. Tsirkin wrote:
> On Sat, Jul 18, 2026 at 10:07:30AM -0700, Carlos Bilbao wrote:
>> On 7/17/26 22:29, Greg Kroah-Hartman wrote:
>>
>>> On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
>>>> Historically, one of the biggest criticisms of coco, especially around
>>>> device hardening, was that there were too many values that a
>>>> malicious/buggy device could misreport, making it a losing battle. That is
>>>> no longer the case with LLMs, and we have the advantage (and challenge) of
>>>> open-source dev, which allows us to receive many of these fixes "for free".
>>>> If others want to burn their tokens, let them :)
>>> I have lots of tokens to burn :)
>>>
>>> So along those lines, any suggestions on how best to fuzz these code
>>> paths? Any workloads you all use for testing that I can take advantage
>>> of?
>>
>> We've the virtio-mem config struct layout and the kernel source, so for
>> obvious fixes like a NULL check, static analysis is better than fuzzing.
>> Claude took a few mins to find me two examples:
>>
>> Patch 1: virtio-mem: reject non-power-of-two device_block_size
>> This one is for virtio_mem_init() to check if
>> !is_power_of_2(vm->device_block_size)
>>
>> Patch 2: virto-mem: validate region_size and usable_region_size
>> THis one checks region_size != 0 and vm->usable_reion_size >
>> vm->region_size.
>>
>> An endless factory of "silly" checks like these are low hanging fruit.
> At the same time, these checks don't actually help within the coco
> threat model, do they?
>
>> Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
>> like a great candidate for those interested in pursuing this direction.
>>
>>
>> Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
>> can't quickly adapt for virtio-mem and other virtio drivers; the JSON
>> definition to describe device behavior is easily extensible. Their threat
>> model [2] describes an external attacker, but in the context of coco, the
>> virtio device itself is the attacker.
> What we need, however, is to exclude DoS attacks - these are outside the
> threat model. If people try to address all DoS attacks uncritically we
> just get a churn of changes which just might introduce issues of their
> own.
>
> Example:
>
> BUG_ON(!is_power_of_2(....));
> panics, non exploitable.
>
> if(!is_power_of_2(....))
> goto error;
>
> can become exploitable if the cleanup is done wrong.
Yes, you are 100% technically right about the scope of the threat model.
DoS is out of scope because it is a fundamentally unreachable goal; the
cloud provider can always just "pull the plug". The dangers of
"vibe-coding" you point out are real, over-eager LLMs fixing up and down
will create new vulnerabilities in complex cleanup paths. Also, TBH, I
sympathize with a maintainer's disinterest in reviewing a million stupid
checks.
But, to play devil's advocate: this assumes a missing check
like is_power_of_2 only ever leads to a benign crash, rather than already
cascading into an unknown, exploitable state down the line.
So these checks are not _just_ to prevent DoS!
Anyhow, this is the exact justification for VirtFuzz. If your main concern
is that adding validation checks might introduce subtle exploit paths in
the error-cleanup code, VirtFuzz and tools like that, can fuzz those new
paths exhaustively. It gives the automated safety net needed to scale coco
device with as little regressions as possible.
>
>
>
>> Here's a vibe coded PR of what I mean:
>>
>> https://github.com/seemoo-lab/VirtFuzz/pull/7
>>
>> CCed the creators/authors, thanks for open sourcing this!
>>
>> Thanks,
>> Carlos
>>
>> [1] https://github.com/seemoo-lab/VirtFuzz
>>
>> On 7/17/26 22:29, Greg Kroah-Hartman wrote:
>>
>>> On Fri, Jul 17, 2026 at 08:31:09PM -0700, Carlos Bilbao wrote:
>>>> Historically, one of the biggest criticisms of coco, especially around
>>>> device hardening, was that there were too many values that a
>>>> malicious/buggy device could misreport, making it a losing battle. That is
>>>> no longer the case with LLMs, and we have the advantage (and challenge) of
>>>> open-source dev, which allows us to receive many of these fixes "for free".
>>>> If others want to burn their tokens, let them :)
>>> I have lots of tokens to burn :)
>>>
>>> So along those lines, any suggestions on how best to fuzz these code
>>> paths? Any workloads you all use for testing that I can take advantage
>>> of?
>>
>> We've the virto-mem config struct layout and the kernel source, so for
>> obvious fixes like a NULL check, static analysis is better than fuzzing.
>> Claude took a few mins to find me two examples:
>>
>> Patch 1: virtio-mem: reject non-power-of-two device_block_size
>> This one is for virtio_mem_init() to check if
>> !is_power_of_2(vm->device_block_size)
>>
>> Patch 2: virto-mem: validate region_size and usable_region_size
>> THis one checks region_size != 0 and vm->usable_reion_size >
>> vm->region_size.
>>
>> An endless factory of "silly" checks like these are low hanging fruit.
>>
>> Now, for harder bugs, looking around for fuzz options, VirtFuzz [1] looks
>> like a great candidate for those interested in pursuing this direction.
>>
>>
>> Their PoC fuzzes wireless/Bluetooth stack, but nothing our AI overlords
>> can't quickly adapt for virtio-mem and other virtio drivers; the JSON
>> definition to describe device behavior is easily extensible. Their threat
>> model [2] describes an external attacker, but in the context of coco, the
>> virtio device itself is the attacker. Here's a vibe coded PR of what I mean:
>>
>> https://github.com/seemoo-lab/VirtFuzz/pull/7
>>
>> CCed the creators/authors, thanks for open sourcing this!
>>
>> Thanks,
>> Carlos
>>
>> [1] https://github.com/seemoo-lab/VirtFuzz
>> [2] https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
>>
>>
>>> thanks,
>>>
>>> greg k-h
>> [2] https://www.computer.org/csdl/proceedings-article/sp/2024/313000a024/1RjEa0y9RMQ
>>
>>
>>> thanks,
>>>
>>> greg k-h
Thanks,
Carlos
^ permalink raw reply
* [PATCH 00/15] drm/drm_simple: remove drm_simple_encoder_init
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
This series open-codes all remaining drm_simple_encoder_init() users by
calling drm_encoder_init() directly and providing driver-local
drm_encoder_funcs where needed. After the driver conversions, the helper
is removed and the completed DRM todo item is dropped.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
Diogo Silva (15):
drm/exynos: remove dependency on DRM simple helpers
drm/xlnx/zynqmp_dpsub: remove dependency on DRM simple helpers
drm/tegra: remove dependency on DRM simple helpers
drm/fsl-dcu: remove dependency on DRM simple helpers
drm/kmb: remove dependency on DRM simple helpers
drm/virtio: remove dependency on DRM simple helpers
drm/tidss: remove dependency on DRM simple helpers
drm/imx: remove dependency on DRM simple helpers
drm/mediatek: remove dependency on DRM simple helpers
drm/renesas/shmobile: remove dependency on DRM simple helpers
drm/hisilicon/kirin: remove dependency on DRM simple helpers
drm/arm/komeda: remove dependency on DRM simple helpers
drm/meson: remove dependency on DRM simple helpers
drm/drm_simple: remove deprecated drm_simple_encoder_init function
Documentation/gpu: remove completed drm_simple_encoder_init() todo
Documentation/gpu/todo.rst | 15 ---------------
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 9 +++++++--
drivers/gpu/drm/drm_simple_kms_helper.c | 13 ++-----------
drivers/gpu/drm/exynos/exynos_dp.c | 13 +++++++++++--
drivers/gpu/drm/exynos/exynos_drm_dpi.c | 14 ++++++++++++--
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 11 +++++++++--
drivers/gpu/drm/exynos/exynos_drm_vidi.c | 14 ++++++++++++--
drivers/gpu/drm/exynos/exynos_hdmi.c | 15 +++++++++++++--
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 10 +++++++---
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 9 +++++++--
drivers/gpu/drm/imx/dc/dc-kms.c | 8 ++++++--
drivers/gpu/drm/kmb/kmb_dsi.c | 9 +++++++--
drivers/gpu/drm/mediatek/mtk_dsi.c | 10 +++++++---
drivers/gpu/drm/meson/meson_encoder_cvbs.c | 11 ++++++++---
drivers/gpu/drm/meson/meson_encoder_dsi.c | 11 ++++++++---
drivers/gpu/drm/meson/meson_encoder_hdmi.c | 11 ++++++++---
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c | 10 +++++++---
drivers/gpu/drm/tegra/dsi.c | 17 ++++++++++++++---
drivers/gpu/drm/tegra/rgb.c | 14 ++++++++++++--
drivers/gpu/drm/tidss/tidss_encoder.c | 10 +++++++---
drivers/gpu/drm/virtio/virtgpu_display.c | 12 ++++++++++--
drivers/gpu/drm/xlnx/zynqmp_kms.c | 13 +++++++++++--
include/drm/drm_simple_kms_helper.h | 4 ----
23 files changed, 185 insertions(+), 78 deletions(-)
---
base-commit: e55c6b9a3522aaf1441a0662d534c1c7bfa9b860
change-id: 20260718-drm_simple_encoder_init-d069a4cc7f8b
Best regards,
--
Diogo Silva <diogompaissilva@gmail.com>
^ permalink raw reply
* [PATCH 01/15] drm/exynos: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Also check the return value from drm_encoder_init() to avoid silent
failures.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/exynos/exynos_dp.c | 13 +++++++++++--
drivers/gpu/drm/exynos/exynos_drm_dpi.c | 14 ++++++++++++--
drivers/gpu/drm/exynos/exynos_drm_dsi.c | 11 +++++++++--
drivers/gpu/drm/exynos/exynos_drm_vidi.c | 14 ++++++++++++--
drivers/gpu/drm/exynos/exynos_hdmi.c | 15 +++++++++++++--
5 files changed, 57 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index b80540328150..1598892c602b 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -24,11 +24,11 @@
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/exynos_drm.h>
#include "exynos_drm_crtc.h"
@@ -79,6 +79,10 @@ static void exynos_dp_nop(struct drm_encoder *encoder)
/* do nothing */
}
+static const struct drm_encoder_funcs exynos_dp_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs exynos_dp_encoder_helper_funcs = {
.mode_set = exynos_dp_mode_set,
.enable = exynos_dp_nop,
@@ -95,7 +99,12 @@ static int exynos_dp_bind(struct device *dev, struct device *master, void *data)
dp->drm_dev = drm_dev;
- drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(drm_dev, encoder, &exynos_dp_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret) {
+ dev_err(dp->dev, "Failed to initialize encoder\n");
+ return ret;
+ }
drm_encoder_helper_add(encoder, &exynos_dp_encoder_helper_funcs);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dpi.c b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
index 0dc36df6ada3..4e42a1da81d1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dpi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dpi.c
@@ -12,10 +12,10 @@
#include <linux/regulator/consumer.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <video/of_videomode.h>
#include <video/videomode.h>
@@ -140,6 +140,10 @@ static void exynos_dpi_disable(struct drm_encoder *encoder)
}
}
+static const struct drm_encoder_funcs exynos_dpi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs exynos_dpi_encoder_helper_funcs = {
.mode_set = exynos_dpi_mode_set,
.enable = exynos_dpi_enable,
@@ -194,7 +198,13 @@ int exynos_dpi_bind(struct drm_device *dev, struct drm_encoder *encoder)
{
int ret;
- drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(dev, encoder, &exynos_dpi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret) {
+ DRM_DEV_ERROR(encoder_to_dpi(encoder)->dev,
+ "failed to create encoder ret = %d\n", ret);
+ return ret;
+ }
drm_encoder_helper_add(encoder, &exynos_dpi_encoder_helper_funcs);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index c4d098ab7863..6b7561ac9bb0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -13,7 +13,7 @@
#include <drm/bridge/samsung-dsim.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_encoder.h>
#include "exynos_drm_crtc.h"
#include "exynos_drm_drv.h"
@@ -22,6 +22,10 @@ struct exynos_dsi {
struct drm_encoder encoder;
};
+static const struct drm_encoder_funcs exynos_drm_dsi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static irqreturn_t exynos_dsi_te_irq_handler(struct samsung_dsim *dsim)
{
struct exynos_dsi *dsi = dsim->priv;
@@ -79,7 +83,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master, void *data
struct drm_device *drm_dev = data;
int ret;
- drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(drm_dev, encoder, &exynos_drm_dsi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret)
+ return ret;
ret = exynos_drm_set_possible_crtcs(encoder, EXYNOS_DISPLAY_TYPE_LCD);
if (ret < 0)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 67bbf9b8bc0e..59dea853d364 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -13,10 +13,10 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include <drm/exynos_drm.h>
@@ -403,6 +403,10 @@ static void exynos_vidi_disable(struct drm_encoder *encoder)
{
}
+static const struct drm_encoder_funcs exynos_vidi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs exynos_vidi_encoder_helper_funcs = {
.mode_set = exynos_vidi_mode_set,
.enable = exynos_vidi_enable,
@@ -445,7 +449,13 @@ static int vidi_bind(struct device *dev, struct device *master, void *data)
return PTR_ERR(ctx->crtc);
}
- drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(drm_dev, encoder, &exynos_vidi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to initialize encoder ret = %d\n",
+ ret);
+ return ret;
+ }
drm_encoder_helper_add(encoder, &exynos_vidi_encoder_helper_funcs);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 09b2cabb236f..f44586ce0fdf 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -36,9 +36,9 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "exynos_drm_crtc.h"
#include "regs-hdmi.h"
@@ -1575,6 +1575,11 @@ static void hdmi_disable(struct drm_encoder *encoder)
mutex_unlock(&hdata->mutex);
}
+static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+
static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = {
.mode_fixup = hdmi_mode_fixup,
.enable = hdmi_enable,
@@ -1862,7 +1867,13 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
hdata->phy_clk.enable = hdmiphy_clk_enable;
- drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(drm_dev, encoder, &exynos_hdmi_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
+ if (ret) {
+ DRM_DEV_ERROR(dev, "failed to initialize encoder ret = %d\n",
+ ret);
+ return ret;
+ }
drm_encoder_helper_add(encoder, &exynos_hdmi_encoder_helper_funcs);
--
2.54.0
^ permalink raw reply related
* [PATCH 02/15] drm/xlnx/zynqmp_dpsub: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Also check the return value from drm_encoder_init() to avoid silent
failures.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/xlnx/zynqmp_kms.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
index d5f922450565..1d194c2824e3 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_kms.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -30,7 +30,6 @@
#include <drm/drm_mode_config.h>
#include <drm/drm_plane.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include <linux/clk.h>
@@ -417,6 +416,10 @@ static const struct drm_driver zynqmp_dpsub_drm_driver = {
.minor = 0,
};
+static const struct drm_encoder_funcs zynqmp_dpsub_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
{
struct drm_encoder *encoder = &dpsub->drm->encoder;
@@ -436,7 +439,13 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
/* Create the encoder and attach the bridge. */
encoder->possible_crtcs |= drm_crtc_mask(&dpsub->drm->crtc);
- drm_simple_encoder_init(&dpsub->drm->dev, encoder, DRM_MODE_ENCODER_NONE);
+ ret = drm_encoder_init(&dpsub->drm->dev, encoder,
+ &zynqmp_dpsub_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
+ if (ret) {
+ dev_err(dpsub->dev, "failed to initialize encoder\n");
+ return ret;
+ }
ret = drm_bridge_attach(encoder, dpsub->bridge, NULL,
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
--
2.54.0
^ permalink raw reply related
* [PATCH 03/15] drm/tegra: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Also check the return value from drm_encoder_init() to avoid silent
failures.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/tegra/dsi.c | 17 ++++++++++++++---
drivers/gpu/drm/tegra/rgb.c | 14 ++++++++++++--
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index e7fdd8c7ac12..840e118716b2 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -20,11 +20,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_file.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
-#include <drm/drm_simple_kms_helper.h>
#include "dc.h"
#include "drm.h"
@@ -1055,6 +1055,10 @@ tegra_dsi_encoder_atomic_check(struct drm_encoder *encoder,
return err;
}
+static const struct drm_encoder_funcs tegra_dsi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
.disable = tegra_dsi_encoder_disable,
.enable = tegra_dsi_encoder_enable,
@@ -1078,8 +1082,15 @@ static int tegra_dsi_init(struct host1x_client *client)
&tegra_dsi_connector_helper_funcs);
dsi->output.connector.dpms = DRM_MODE_DPMS_OFF;
- drm_simple_encoder_init(drm, &dsi->output.encoder,
- DRM_MODE_ENCODER_DSI);
+ err = drm_encoder_init(drm, &dsi->output.encoder,
+ &tegra_dsi_encoder_funcs,
+ DRM_MODE_ENCODER_DSI, NULL);
+ if (err) {
+ dev_err(dsi->dev, "failed to initialize encoder: %d\n",
+ err);
+ return err;
+ }
+
drm_encoder_helper_add(&dsi->output.encoder,
&tegra_dsi_encoder_helper_funcs);
diff --git a/drivers/gpu/drm/tegra/rgb.c b/drivers/gpu/drm/tegra/rgb.c
index e67fbb2362e6..337925c30d67 100644
--- a/drivers/gpu/drm/tegra/rgb.c
+++ b/drivers/gpu/drm/tegra/rgb.c
@@ -9,7 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge_connector.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_encoder.h>
#include "drm.h"
#include "dc.h"
@@ -194,6 +194,10 @@ tegra_rgb_encoder_atomic_check(struct drm_encoder *encoder,
return err;
}
+static const struct drm_encoder_funcs tegra_rgb_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs tegra_rgb_encoder_helper_funcs = {
.disable = tegra_rgb_encoder_disable,
.enable = tegra_rgb_encoder_enable,
@@ -305,7 +309,13 @@ int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc)
if (!dc->rgb)
return -ENODEV;
- drm_simple_encoder_init(drm, &output->encoder, DRM_MODE_ENCODER_LVDS);
+ err = drm_encoder_init(drm, &output->encoder, &tegra_rgb_encoder_funcs,
+ DRM_MODE_ENCODER_LVDS, NULL);
+ if (err) {
+ dev_err(output->dev, "failed to initialize encoder: %d\n", err);
+ return err;
+ }
+
drm_encoder_helper_add(&output->encoder,
&tegra_rgb_encoder_helper_funcs);
--
2.54.0
^ permalink raw reply related
* [PATCH 04/15] drm/fsl-dcu: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
index 84eff7519e32..c2b788bfa8f9 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
@@ -11,14 +11,18 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "fsl_dcu_drm_drv.h"
#include "fsl_tcon.h"
+static const struct drm_encoder_funcs fsl_dcu_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
struct drm_crtc *crtc)
{
@@ -31,8 +35,8 @@ int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev,
if (fsl_dev->tcon)
fsl_tcon_bypass_enable(fsl_dev->tcon);
- ret = drm_simple_encoder_init(fsl_dev->drm, encoder,
- DRM_MODE_ENCODER_LVDS);
+ ret = drm_encoder_init(fsl_dev->drm, encoder, &fsl_dcu_encoder_funcs,
+ DRM_MODE_ENCODER_LVDS, NULL);
if (ret < 0)
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 05/15] drm/kmb: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/kmb/kmb_dsi.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/kmb/kmb_dsi.c b/drivers/gpu/drm/kmb/kmb_dsi.c
index 59d0e856392f..13adba96bc78 100644
--- a/drivers/gpu/drm/kmb/kmb_dsi.c
+++ b/drivers/gpu/drm/kmb/kmb_dsi.c
@@ -14,8 +14,8 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
@@ -1427,6 +1427,10 @@ struct kmb_dsi *kmb_dsi_init(struct platform_device *pdev)
return kmb_dsi;
}
+static const struct drm_encoder_funcs kmb_dsi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi)
{
struct drm_encoder *encoder;
@@ -1437,7 +1441,8 @@ int kmb_dsi_encoder_init(struct drm_device *dev, struct kmb_dsi *kmb_dsi)
encoder->possible_crtcs = 1;
encoder->possible_clones = 0;
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_DSI);
+ ret = drm_encoder_init(dev, encoder, &kmb_dsi_encoder_funcs,
+ DRM_MODE_ENCODER_DSI, NULL);
if (ret) {
dev_err(kmb_dsi->dev, "Failed to init encoder %d\n", ret);
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 06/15] drm/virtio: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Also check the return value from drm_encoder_init() to avoid silent
failures.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/virtio/virtgpu_display.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 44ffffec550f..67023d91d40b 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -28,11 +28,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include <drm/drm_vblank_helper.h>
@@ -232,6 +232,10 @@ static enum drm_mode_status virtio_gpu_conn_mode_valid(struct drm_connector *con
return MODE_BAD;
}
+static const struct drm_encoder_funcs virtio_gpu_enc_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs virtio_gpu_enc_helper_funcs = {
.mode_set = virtio_gpu_enc_mode_set,
.enable = virtio_gpu_enc_enable,
@@ -306,7 +310,11 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
if (vgdev->has_edid)
drm_connector_attach_edid_property(connector);
- drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_VIRTUAL);
+ ret = drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs,
+ DRM_MODE_ENCODER_VIRTUAL, NULL);
+ if (ret)
+ return ret;
+
drm_encoder_helper_add(encoder, &virtio_gpu_enc_helper_funcs);
encoder->possible_crtcs = 1 << index;
--
2.54.0
^ permalink raw reply related
* [PATCH 07/15] drm/tidss: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/tidss/tidss_encoder.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/tidss/tidss_encoder.c b/drivers/gpu/drm/tidss/tidss_encoder.c
index 698f8d964ca0..10dbcc6cdf6a 100644
--- a/drivers/gpu/drm/tidss/tidss_encoder.c
+++ b/drivers/gpu/drm/tidss/tidss_encoder.c
@@ -9,11 +9,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_crtc.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_panel.h>
#include <drm/drm_of.h>
-#include <drm/drm_simple_kms_helper.h>
#include "tidss_crtc.h"
#include "tidss_drv.h"
@@ -81,6 +81,10 @@ static const struct drm_bridge_funcs tidss_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
};
+static const struct drm_encoder_funcs tidss_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int tidss_encoder_create(struct tidss_device *tidss,
struct drm_bridge *next_bridge,
u32 encoder_type, u32 possible_crtcs)
@@ -95,8 +99,8 @@ int tidss_encoder_create(struct tidss_device *tidss,
if (IS_ERR(t_enc))
return PTR_ERR(t_enc);
- ret = drm_simple_encoder_init(&tidss->ddev, &t_enc->encoder,
- encoder_type);
+ ret = drm_encoder_init(&tidss->ddev, &t_enc->encoder,
+ &tidss_encoder_funcs, encoder_type, NULL);
if (ret)
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 08/15] drm/imx: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/imx/dc/dc-kms.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/imx/dc/dc-kms.c b/drivers/gpu/drm/imx/dc/dc-kms.c
index 0f8cfaf4c4d1..a9adcfc68b84 100644
--- a/drivers/gpu/drm/imx/dc/dc-kms.c
+++ b/drivers/gpu/drm/imx/dc/dc-kms.c
@@ -17,7 +17,6 @@
#include <drm/drm_mode_config.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include "dc-de.h"
@@ -30,6 +29,10 @@ static const struct drm_mode_config_funcs dc_drm_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit,
};
+static const struct drm_encoder_funcs dc_kms_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static int dc_kms_init_encoder_per_crtc(struct dc_drm_device *dc_drm,
int crtc_index)
{
@@ -55,7 +58,8 @@ static int dc_kms_init_encoder_per_crtc(struct dc_drm_device *dc_drm,
}
encoder = &dc_drm->encoder[crtc_index];
- ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE);
+ ret = drm_encoder_init(drm, encoder, &dc_kms_encoder_funcs,
+ DRM_MODE_ENCODER_NONE, NULL);
if (ret) {
dev_err(dev, "failed to initialize encoder for CRTC%u: %d\n",
crtc->index, ret);
--
2.54.0
^ permalink raw reply related
* [PATCH 09/15] drm/mediatek: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/mediatek/mtk_dsi.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 3f3f56eed3f9..7cd136bd9605 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -21,12 +21,12 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "mtk_ddp_comp.h"
#include "mtk_disp_drv.h"
@@ -913,12 +913,16 @@ void mtk_dsi_ddp_stop(struct device *dev)
mtk_dsi_poweroff(dsi);
}
+static const struct drm_encoder_funcs mtk_dsi_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
{
int ret;
- ret = drm_simple_encoder_init(drm, &dsi->encoder,
- DRM_MODE_ENCODER_DSI);
+ ret = drm_encoder_init(drm, &dsi->encoder, &mtk_dsi_encoder_funcs,
+ DRM_MODE_ENCODER_DSI, NULL);
if (ret) {
drm_err(drm, "Failed to encoder init to drm\n");
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 10/15] drm/renesas/shmobile: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
index 1a2b9b68af6f..2dc477c7eda6 100644
--- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
@@ -21,6 +21,7 @@
#include <drm/drm_bridge_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
@@ -29,7 +30,6 @@
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_panel.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vblank.h>
#include <video/videomode.h>
@@ -436,6 +436,10 @@ static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
.mode_fixup = shmob_drm_encoder_mode_fixup,
};
+static const struct drm_encoder_funcs shmob_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
/* -----------------------------------------------------------------------------
* Encoder
*/
@@ -448,8 +452,8 @@ int shmob_drm_encoder_create(struct shmob_drm_device *sdev)
encoder->possible_crtcs = 1;
- ret = drm_simple_encoder_init(&sdev->ddev, encoder,
- DRM_MODE_ENCODER_DPI);
+ ret = drm_encoder_init(&sdev->ddev, encoder, &shmob_encoder_funcs,
+ DRM_MODE_ENCODER_DPI, NULL);
if (ret < 0)
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 11/15] drm/hisilicon/kirin: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index 15042365dec0..62c5bd3277da 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -20,11 +20,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_device.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "dw_dsi_reg.h"
@@ -687,6 +687,10 @@ static int dsi_encoder_atomic_check(struct drm_encoder *encoder,
return 0;
}
+static const struct drm_encoder_funcs dw_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static const struct drm_encoder_helper_funcs dw_encoder_helper_funcs = {
.atomic_check = dsi_encoder_atomic_check,
.mode_valid = dsi_encoder_mode_valid,
@@ -708,7 +712,8 @@ static int dw_drm_encoder_init(struct device *dev,
}
encoder->possible_crtcs = crtc_mask;
- ret = drm_simple_encoder_init(drm_dev, encoder, DRM_MODE_ENCODER_DSI);
+ ret = drm_encoder_init(drm_dev, encoder, &dw_encoder_funcs,
+ DRM_MODE_ENCODER_DSI, NULL);
if (ret) {
DRM_ERROR("failed to init dsi encoder\n");
return ret;
--
2.54.0
^ permalink raw reply related
* [PATCH 12/15] drm/arm/komeda: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
index e8cb782a6f8e..719568d9f7c2 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c
@@ -11,9 +11,9 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_bridge.h>
#include "komeda_dev.h"
@@ -635,6 +635,10 @@ static int komeda_attach_bridge(struct device *dev,
return err;
}
+static const struct drm_encoder_funcs komeda_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
static int komeda_crtc_add(struct komeda_kms_dev *kms,
struct komeda_crtc *kcrtc)
{
@@ -658,7 +662,8 @@ static int komeda_crtc_add(struct komeda_kms_dev *kms,
* bridge
*/
kcrtc->encoder.possible_crtcs = drm_crtc_mask(crtc);
- err = drm_simple_encoder_init(base, encoder, DRM_MODE_ENCODER_TMDS);
+ err = drm_encoder_init(base, encoder, &komeda_encoder_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
if (err)
return err;
--
2.54.0
^ permalink raw reply related
* [PATCH 13/15] drm/meson: remove dependency on DRM simple helpers
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
Open-code drm_simple_encoder_init() by calling drm_encoder_init()
directly and providing driver-local drm_encoder_funcs.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/meson/meson_encoder_cvbs.c | 11 ++++++++---
drivers/gpu/drm/meson/meson_encoder_dsi.c | 11 ++++++++---
drivers/gpu/drm/meson/meson_encoder_hdmi.c | 11 ++++++++---
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
index 22cacb1660c4..cdb84d2283f8 100644
--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
@@ -17,8 +17,8 @@
#include <drm/drm_bridge_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include "meson_registers.h"
#include "meson_vclk.h"
@@ -218,6 +218,10 @@ static const struct drm_bridge_funcs meson_encoder_cvbs_bridge_funcs = {
.atomic_create_state = drm_atomic_helper_bridge_create_state,
};
+static const struct drm_encoder_funcs meson_encoder_cvbs_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int meson_encoder_cvbs_probe(struct meson_drm *priv)
{
struct drm_device *drm = priv->drm;
@@ -257,8 +261,9 @@ int meson_encoder_cvbs_probe(struct meson_drm *priv)
meson_encoder_cvbs->priv = priv;
/* Encoder */
- ret = drm_simple_encoder_init(priv->drm, &meson_encoder_cvbs->encoder,
- DRM_MODE_ENCODER_TVDAC);
+ ret = drm_encoder_init(priv->drm, &meson_encoder_cvbs->encoder,
+ &meson_encoder_cvbs_funcs,
+ DRM_MODE_ENCODER_TVDAC, NULL);
if (ret)
return dev_err_probe(priv->dev, ret,
"Failed to init CVBS encoder\n");
diff --git a/drivers/gpu/drm/meson/meson_encoder_dsi.c b/drivers/gpu/drm/meson/meson_encoder_dsi.c
index 3e422b612f74..faa309cb97a6 100644
--- a/drivers/gpu/drm/meson/meson_encoder_dsi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_dsi.c
@@ -10,10 +10,10 @@
#include <linux/of_graph.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_device.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_probe_helper.h>
#include "meson_drv.h"
@@ -99,6 +99,10 @@ static const struct drm_bridge_funcs meson_encoder_dsi_bridge_funcs = {
.atomic_create_state = drm_atomic_helper_bridge_create_state,
};
+static const struct drm_encoder_funcs meson_encoder_dsi_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int meson_encoder_dsi_probe(struct meson_drm *priv)
{
struct meson_encoder_dsi *meson_encoder_dsi;
@@ -133,8 +137,9 @@ int meson_encoder_dsi_probe(struct meson_drm *priv)
meson_encoder_dsi->priv = priv;
/* Encoder */
- ret = drm_simple_encoder_init(priv->drm, &meson_encoder_dsi->encoder,
- DRM_MODE_ENCODER_DSI);
+ ret = drm_encoder_init(priv->drm, &meson_encoder_dsi->encoder,
+ &meson_encoder_dsi_funcs, DRM_MODE_ENCODER_DSI,
+ NULL);
if (ret)
return dev_err_probe(priv->dev, ret,
"Failed to init DSI encoder\n");
diff --git a/drivers/gpu/drm/meson/meson_encoder_hdmi.c b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
index 0c7a72cb514a..c4355c5cc340 100644
--- a/drivers/gpu/drm/meson/meson_encoder_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_encoder_hdmi.c
@@ -23,8 +23,8 @@
#include <drm/drm_bridge_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <linux/media-bus-format.h>
#include <linux/videodev2.h>
@@ -369,6 +369,10 @@ static const struct drm_bridge_funcs meson_encoder_hdmi_bridge_funcs = {
.atomic_create_state = drm_atomic_helper_bridge_create_state,
};
+static const struct drm_encoder_funcs meson_encoder_hdmi_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
int meson_encoder_hdmi_probe(struct meson_drm *priv)
{
struct meson_encoder_hdmi *meson_encoder_hdmi;
@@ -407,8 +411,9 @@ int meson_encoder_hdmi_probe(struct meson_drm *priv)
meson_encoder_hdmi->priv = priv;
/* Encoder */
- ret = drm_simple_encoder_init(priv->drm, &meson_encoder_hdmi->encoder,
- DRM_MODE_ENCODER_TMDS);
+ ret = drm_encoder_init(priv->drm, &meson_encoder_hdmi->encoder,
+ &meson_encoder_hdmi_funcs,
+ DRM_MODE_ENCODER_TMDS, NULL);
if (ret) {
dev_err_probe(priv->dev, ret, "Failed to init HDMI encoder\n");
goto err_put_node;
--
2.54.0
^ permalink raw reply related
* [PATCH 14/15] drm/drm_simple: remove deprecated drm_simple_encoder_init function
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
The simple KMS helpers are deprecated because they only add an
intermediate layer between drivers and atomic modesetting.
All driver users of drm_simple_encoder_init() have been converted to
drm_encoder_init(). Drop the helper and open-code its remaining internal
use in drm_simple_display_pipe_init() to prevent new users.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
drivers/gpu/drm/drm_simple_kms_helper.c | 13 ++-----------
include/drm/drm_simple_kms_helper.h | 4 ----
2 files changed, 2 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index 8e1d07b9f1e3..7878b9d7d524 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -20,16 +20,6 @@ static const struct drm_encoder_funcs drm_simple_encoder_funcs_cleanup = {
.destroy = drm_encoder_cleanup,
};
-int drm_simple_encoder_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- int encoder_type)
-{
- return drm_encoder_init(dev, encoder,
- &drm_simple_encoder_funcs_cleanup,
- encoder_type, NULL);
-}
-EXPORT_SYMBOL(drm_simple_encoder_init);
-
void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size,
size_t offset, int encoder_type)
{
@@ -363,7 +353,8 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_NONE);
+ ret = drm_encoder_init(dev, encoder, &drm_simple_encoder_funcs_cleanup,
+ DRM_MODE_ENCODER_NONE, NULL);
if (ret || !connector)
return ret;
diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h
index cb672ce0e856..c95f86ff355f 100644
--- a/include/drm/drm_simple_kms_helper.h
+++ b/include/drm/drm_simple_kms_helper.h
@@ -68,10 +68,6 @@ int drm_simple_display_pipe_init(struct drm_device *dev,
const uint64_t *format_modifiers,
struct drm_connector *connector);
-int drm_simple_encoder_init(struct drm_device *dev,
- struct drm_encoder *encoder,
- int encoder_type);
-
void *__drmm_simple_encoder_alloc(struct drm_device *dev, size_t size,
size_t offset, int encoder_type);
--
2.54.0
^ permalink raw reply related
* [PATCH 15/15] Documentation/gpu: remove completed drm_simple_encoder_init() todo
From: Diogo Silva @ 2026-07-18 23:35 UTC (permalink / raw)
To: Jingoo Han, Inki Dae, Seung-Woo Kim, Kyungmin Park, David Airlie,
Simona Vetter, Krzysztof Kozlowski, Peter Griffin, Alim Akhtar,
Laurent Pinchart, Tomi Valkeinen, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, Michal Simek, Thierry Reding,
Mikko Perttunen, Jonathan Hunter, Stefan Agner, Alison Wang,
Anitha Chrisanthus, David Airlie, Gerd Hoffmann, Dmitry Osipenko,
Gurchetan Singh, Chia-I Wu, Jyri Sarha, Liu Ying, Frank Li,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Chun-Kuang Hu, Philipp Zabel, Matthias Brugger,
AngeloGioacchino Del Regno, Geert Uytterhoeven, Xinliang Liu,
Sumit Semwal, Yongqin Liu, John Stultz, Liviu Dudau,
Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
Jonathan Corbet, Shuah Khan
Cc: dri-devel, linux-arm-kernel, linux-samsung-soc, linux-kernel,
linux-tegra, virtualization, imx, linux-mediatek,
linux-renesas-soc, linux-amlogic, linux-doc, Diogo Silva
In-Reply-To: <20260719-drm_simple_encoder_init-v1-0-a78c509e3062@gmail.com>
All drm_simple_encoder_init() users have been removed, so drop the
completed todo item.
Signed-off-by: Diogo Silva <diogompaissilva@gmail.com>
---
Documentation/gpu/todo.rst | 15 ---------------
1 file changed, 15 deletions(-)
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 14cf37590fc7..b7351467dc74 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -29,21 +29,6 @@ refactorings already and are an expert in the specific area
Subsystem-wide refactorings
===========================
-Open-code drm_simple_encoder_init()
------------------------------------
-
-The helper drm_simple_encoder_init() was supposed to simplify encoder
-initialization. Instead it only added an intermediate layer between atomic
-modesetting and the DRM driver.
-
-The task here is to remove drm_simple_encoder_init(). Search for a driver
-that calls drm_simple_encoder_init() and inline the helper. The driver will
-also need its own instance of drm_encoder_funcs.
-
-Contact: Thomas Zimmermann, respective driver maintainer
-
-Level: Easy
-
Replace struct drm_simple_display_pipe with regular atomic helpers
------------------------------------------------------------------
--
2.54.0
^ permalink raw reply related
* Re: [PATCH 6.12] vsock/virtio: fix zerocopy completion for multi-skb sends
From: Sasha Levin @ 2026-07-19 15:00 UTC (permalink / raw)
To: stable, Greg Kroah-Hartman
Cc: Sasha Levin, Alexander Martyniuk, lvc-project, Michael S. Tsirkin,
Jason Wang, Xuan Zhuo, Eugenio Pérez, Stefan Hajnoczi,
Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Arseniy Krasnov, virtualization, kvm,
netdev, linux-kernel, Maher Azzouzi
In-Reply-To: <20260716163600.115458-1-alexevgmart@gmail.com>
> When a large message is fragmented into multiple skbs, the zerocopy
> uarg is only allocated and attached to the last skb in the loop.
> Non-final skbs carry pinned user pages with no completion tracking,
> so the kernel has no way to notify userspace when those pages are safe
> to reuse.
Queued for 6.12, thanks.
--
Thanks,
Sasha
^ permalink raw reply
* [PATCH] vsock: use sock_error() to consume sk_err after connect timeout
From: Nguyen Dinh Phi @ 2026-07-19 21:57 UTC (permalink / raw)
To: Stefano Garzarella, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: Nguyen Dinh Phi, syzbot+1b2c9c4a0f8708082678, virtualization,
netdev, linux-kernel
After vsock_connect() exits the wait loop due to sk->sk_err being
set, the error was read but not cleared. This left sk->sk_err set
for subsequent operations.
Switch to sock_error() which atomically reads and clears sk->sk_err,
so the error is consumed when returned.
Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
Reported-by: syzbot+1b2c9c4a0f8708082678@syzkaller.appspotmail.com
---
net/vmw_vsock/af_vsock.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 622dbd046799..43eddc33ed12 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -1847,14 +1847,11 @@ static int vsock_connect(struct socket *sock, struct sockaddr_unsized *addr,
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
}
- if (sk->sk_err) {
- err = -sk->sk_err;
+ err = sock_error(sk);
+ if (err) {
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
- } else {
- err = 0;
}
-
out_wait:
finish_wait(sk_sleep(sk), &wait);
out:
--
2.53.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox