From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9911547426B for ; Thu, 23 Jul 2026 18:33:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.197 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784831593; cv=none; b=Lm3G62ulZxCc9MXxhEzngMCrOs3Z3O4OkhWf1xayHNtGJ5lqfcPoT1ySnq024LrYvAeUD+CjxgLPn8QQSm6WTe2Ur0tOIAR+YXCC2CG6Oy511iAa1HB1k0zwlzZSb26cwLX+bBEZB0uZ7tQbWX83FMyJUdemo3RN/lR7Fb1pDDo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784831593; c=relaxed/simple; bh=vDZeQinpdFoDcNuImf1N/0AjNHp4brVkSFrAhi9TCPw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ncZpaFxQqNZEGwbl3rUtKGXVjLviZXqCFbGdjAzk7Na0ibjY5ta38gcY2CjAXT/gMwp1h15dZ03O4h/rF8eWiQ59f4EHsL5pGy4h+B8N0E5vgdhO/kt7vOPC0lTbF1+vtSSfMMfS56aBJSwfe+8Xtr/Qn/cXbXYLSOgI090RF7M= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--briandaniels.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=uAGn3DgF; arc=none smtp.client-ip=209.85.160.197 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--briandaniels.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="uAGn3DgF" Received: by mail-qt1-f197.google.com with SMTP id d75a77b69052e-5174a236220so18370951cf.3 for ; Thu, 23 Jul 2026 11:33:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1784831581; x=1785436381; darn=vger.kernel.org; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:from:to:cc:subject:date:message-id:reply-to :content-type; bh=lqiWQikS8RfwgMFdKdTRhH3oYvJSP9R+oKdTrkEuptE=; b=uAGn3DgFLb/cZPH4Kw68dulrAsC1o4k1LWSIRqxncvOenAZMwHa96JSzOfqfTj5Amk umUNU4QDukMf3KVUDzbmIZnkTIFiPa92jWpALj5kIh+Rnze5buhCv/k89fmaTrrJ4tir N2SD+mM9YFHmklTUw9CvlCe3ZtDA6rLnvXPC9sOdz1DVYg7riybgauqCLCK/1w7sg3us J2WDleloZ5ewjWLDT2D+/iZU3BCbzE6HTdfJ6Vvnu3qsyPob1DcblWOk+x5nKwaJQjYS cU9t/fyCOMJEhrv1by00XpAN7/r061HMwHe9NBOK4aVXoz5Fyk6N093bU04BEO5ifWBT 2wYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784831581; x=1785436381; h=content-type:cc:to:from:subject:message-id:references:mime-version :in-reply-to:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=lqiWQikS8RfwgMFdKdTRhH3oYvJSP9R+oKdTrkEuptE=; b=fQb8UBaAfgl7aA5e8q/Fziz0gPYxcyKgJJxmv6uv7UPISS/dnz+ui6Gyof2dYqIPnZ Pj36T/Dzey/0+Ce7Jn7JoirmyBM7Op9L99e+6ELk9utclZ1ATAgcoSf1DgP/2q4+fc6O RpZQNVVomlzHLCAZL+IikhX/Pa32ygg0GsEFYR9f3Ve9KIEnEaWd3IfAK5iUvtGvsaVz zM+22lnbgbiWbn5x0/m3VqXqOuqeAM2ZkzJvVctn3PlnaTL1o4ztSNqz+aEbKPrCQs+V K8zpVO4ogb8/86lgl7sy0krpsrav9RPS177JA33A7QbZGaSsdXMCu/kNyIsrC54YJfob SyuQ== X-Forwarded-Encrypted: i=1; AHgh+RpDtNl9n0QnL8XtkJIcQsg5O1/Ob58/2XEPSESbqrnq+theldyZMdjopKACLkMZuoW4zdL8sXDBdrBiyA==@vger.kernel.org X-Gm-Message-State: AOJu0YwPGXO+mIV0Xj3LL+8+/igL60KglF1zDf1Z8luctFK2dRtr51Wu bBYNbl07DuTXJ4X1jKUX4sZMKxGAbvCSMUAFUrINjHXC7vtS2t5oXHsYqZRNOLu6khgOryGJVrm Yl8jhDJzkBxdSxRcw6xzp/U4RMWKP X-Received: from qtbob13.prod.google.com ([2002:a05:622a:7d8d:b0:520:227f:57c8]) (user=briandaniels job=prod-delivery.src-stubby-dispatcher) by 2002:a05:622a:830f:b0:526:f9e1:9e50 with SMTP id d75a77b69052e-528459f1a4dmr20080541cf.47.1784831580814; Thu, 23 Jul 2026 11:33:00 -0700 (PDT) Date: Thu, 23 Jul 2026 14:32:19 -0400 In-Reply-To: <20260723183219.737296-1-briandaniels@google.com> Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260723183219.737296-1-briandaniels@google.com> X-Mailer: git-send-email 2.55.0.229.g6434b31f56-goog Message-ID: <20260723183219.737296-6-briandaniels@google.com> Subject: [PATCH v5 5/5] media: virtio: Add USERPTR memory type support From: Brian Daniels To: Mauro Carvalho Chehab Cc: adelva@google.com, aesteve@redhat.com, changyeon@google.com, daniel.almeida@collabora.com, eperezma@redhat.com, gnurou@gmail.com, gurchetansingh@google.com, hverkuil@xs4all.nl, jasowang@redhat.com, linux-kernel@vger.kernel.org, linux-media@vger.kernel.org, mst@redhat.com, nicolas.dufresne@collabora.com, virtualization@lists.linux.dev, xuanzhuo@linux.alibaba.com, Brian Daniels Content-Type: text/plain; charset="UTF-8" From: Alexandre Courbot This patch adds support for the USERPTR memory type to the virtio-media driver. It adds the allow_userptr module parameter, implements the userptr mapping logic in the scatterlist builder, and enables USERPTR in reqbufs if allowed. Signed-off-by: Alexandre Courbot Assisted-by: Antigravity:gemini-3.5-flash Co-developed-by: Brian Daniels Signed-off-by: Brian Daniels --- drivers/media/virtio/scatterlist_builder.c | 64 ++++++++++++++++++++++ drivers/media/virtio/scatterlist_builder.h | 3 + drivers/media/virtio/virtio_media_driver.c | 42 +++++++++----- drivers/media/virtio/virtio_media_ioctls.c | 11 +++- 4 files changed, 104 insertions(+), 16 deletions(-) diff --git a/drivers/media/virtio/scatterlist_builder.c b/drivers/media/virtio/scatterlist_builder.c index 97925b277..85c6a36b4 100644 --- a/drivers/media/virtio/scatterlist_builder.c +++ b/drivers/media/virtio/scatterlist_builder.c @@ -349,14 +349,30 @@ static int scatterlist_builder_add_userptr(struct scatterlist_builder *builder, int scatterlist_builder_add_buffer(struct scatterlist_builder *builder, struct v4l2_buffer *b) { + int i; int ret; + /* Fixup: plane length must be zero if userptr is NULL */ + if (!V4L2_TYPE_IS_MULTIPLANAR(b->type) && + b->memory == V4L2_MEMORY_USERPTR && b->m.userptr == 0) + b->length = 0; + /* v4l2_buffer */ ret = scatterlist_builder_add_data(builder, b, sizeof(*b)); if (ret) return ret; if (V4L2_TYPE_IS_MULTIPLANAR(b->type) && b->length > 0) { + /* Fixup: plane length must be zero if userptr is NULL */ + if (b->memory == V4L2_MEMORY_USERPTR) { + for (i = 0; i < b->length; i++) { + struct v4l2_plane *plane = &b->m.planes[i]; + + if (plane->m.userptr == 0) + plane->length = 0; + } + } + /* Array of v4l2_planes */ ret = scatterlist_builder_add_data(builder, b->m.planes, sizeof(struct v4l2_plane) * @@ -368,6 +384,54 @@ int scatterlist_builder_add_buffer(struct scatterlist_builder *builder, return 0; } +/** + * scatterlist_builder_add_buffer_userptr() - Add the payload of a ``USERPTR`` + * &struct v4l2_buffer to the + * descriptor chain. + * @builder: builder to use. + * @b: &struct v4l2_buffer whose ``USERPTR`` payload we want to add. + * + * Add an array of &struct virtio_media_sg_entry pointing to a ``USERPTR`` + * buffer's contents. Does nothing if the buffer is not of type ``USERPTR``. + * This is split out of scatterlist_builder_add_buffer() because we only want + * to add these to the device-readable part of the descriptor chain. + */ +int scatterlist_builder_add_buffer_userptr(struct scatterlist_builder *builder, + struct v4l2_buffer *b) +{ + int i; + int ret; + + if (b->memory != V4L2_MEMORY_USERPTR) + return 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + for (i = 0; i < b->length; i++) { + struct v4l2_plane *plane = &b->m.planes[i]; + + if (b->memory == V4L2_MEMORY_USERPTR && + plane->length > 0) { + unsigned long uptr = plane->m.userptr; + unsigned long len = plane->length; + + ret = + scatterlist_builder_add_userptr(builder, + uptr, + len); + if (ret) + return ret; + } + } + } else if (b->length > 0) { + ret = scatterlist_builder_add_userptr(builder, b->m.userptr, + b->length); + if (ret) + return ret; + } + + return 0; +} + /** * scatterlist_builder_retrieve_buffer() - Retrieve a &struct v4l2_buffer * written by the device on the shadow diff --git a/drivers/media/virtio/scatterlist_builder.h b/drivers/media/virtio/scatterlist_builder.h index 47bfd7ae0..53d964a48 100644 --- a/drivers/media/virtio/scatterlist_builder.h +++ b/drivers/media/virtio/scatterlist_builder.h @@ -90,6 +90,9 @@ int scatterlist_builder_add_ioctl_resp(struct scatterlist_builder *builder, int scatterlist_builder_add_buffer(struct scatterlist_builder *builder, struct v4l2_buffer *buffer); +int scatterlist_builder_add_buffer_userptr(struct scatterlist_builder *builder, + struct v4l2_buffer *b); + int scatterlist_builder_retrieve_buffer(struct scatterlist_builder *builder, size_t sg_index, struct v4l2_buffer *buffer, diff --git a/drivers/media/virtio/virtio_media_driver.c b/drivers/media/virtio/virtio_media_driver.c index c431c3eb2..b6f79593d 100644 --- a/drivers/media/virtio/virtio_media_driver.c +++ b/drivers/media/virtio/virtio_media_driver.c @@ -7,26 +7,29 @@ */ #include +#include #include #include +#include #include +#include #include +#include +#include +#include +#include #include +#include #include #include #include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include #include +#include +#include +#include #include "uapi/linux/virtio_media.h" #include "session.h" @@ -40,6 +43,15 @@ /* Bit mask for the VIRTIO_MEDIA_MMAP_FLAG_RW flag */ #define VIRTIO_MEDIA_MMAP_FLAG_RW_MASK BIT(VIRTIO_MEDIA_MMAP_FLAG_RW) +/* + * 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); + /** * virtio_media_session_alloc() - Allocate a new session. * @vv: virtio-media device the session belongs to. @@ -849,15 +861,11 @@ static int virtio_media_probe(struct virtio_device *virtio_dev) 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->release = video_device_release_empty; - strscpy(vd->name, "virtio-media", sizeof(vd->name)); - - video_set_drvdata(vd, vv); - 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; @@ -866,6 +874,10 @@ static int virtio_media_probe(struct virtio_device *virtio_dev) 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) @@ -890,6 +902,7 @@ static int virtio_media_probe(struct virtio_device *virtio_dev) virtio_dev->config->del_vqs(virtio_dev); err_find_vqs: v4l2_device_unregister(&vv->v4l2_dev); + return ret; } @@ -900,6 +913,7 @@ static void virtio_media_remove(struct virtio_device *virtio_dev) 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); diff --git a/drivers/media/virtio/virtio_media_ioctls.c b/drivers/media/virtio/virtio_media_ioctls.c index f0b82b5ec..88465f239 100644 --- a/drivers/media/virtio/virtio_media_ioctls.c +++ b/drivers/media/virtio/virtio_media_ioctls.c @@ -273,6 +273,12 @@ static int virtio_media_send_buffer_ioctl(struct v4l2_fh *fh, u32 ioctl, return ret; end_buf_sg = builder.cur_sg; + + /* Payload of SHARED_PAGES buffers, if relevant */ + ret = scatterlist_builder_add_buffer_userptr(&builder, b); + if (ret < 0) + return ret; + num_cmd_sgs = builder.cur_sg; /* Response descriptor */ @@ -719,7 +725,7 @@ static int virtio_media_reqbufs(struct file *file, void *fh, if (b->type > VIRTIO_MEDIA_LAST_QUEUE) return -EINVAL; - if (b->memory == V4L2_MEMORY_USERPTR) + if (b->memory == V4L2_MEMORY_USERPTR && !virtio_media_allow_userptr) return -EINVAL; ret = virtio_media_send_wr_ioctl(vfh, VIDIOC_REQBUFS, b, sizeof(*b), @@ -752,7 +758,8 @@ static int virtio_media_reqbufs(struct file *file, void *fh, if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) session->uses_mplane = true; - b->capabilities &= ~V4L2_BUF_CAP_SUPPORTS_USERPTR; + if (!virtio_media_allow_userptr) + b->capabilities &= ~V4L2_BUF_CAP_SUPPORTS_USERPTR; /* We do not support DMABUF yet. */ b->capabilities &= ~V4L2_BUF_CAP_SUPPORTS_DMABUF; -- 2.55.0.229.g6434b31f56-goog