Show a patch.

GET /api/patches/20189/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 20189,
    "url": "https://patchwork.libcamera.org/api/patches/20189/?format=api",
    "web_url": "https://patchwork.libcamera.org/patch/20189/",
    "project": {
        "id": 1,
        "url": "https://patchwork.libcamera.org/api/projects/1/?format=api",
        "name": "libcamera",
        "link_name": "libcamera",
        "list_id": "libcamera_core",
        "list_email": "libcamera-devel@lists.libcamera.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": ""
    },
    "msgid": "<20240603111259.54321-3-hdegoede@redhat.com>",
    "date": "2024-06-03T11:12:58",
    "name": "[v3,2/3] libcamera: DmaBufAllocator: Support allocating from /dev/udmabuf",
    "commit_ref": "ea4baaacc3250eadb929fcef59bb9ddefb012952",
    "pull_url": null,
    "state": "accepted",
    "archived": false,
    "hash": "af1badb5eea69ea2bd6fc38cfaeecf02ed9eb700",
    "submitter": {
        "id": 102,
        "url": "https://patchwork.libcamera.org/api/people/102/?format=api",
        "name": "Hans de Goede",
        "email": "hdegoede@redhat.com"
    },
    "delegate": null,
    "mbox": "https://patchwork.libcamera.org/patch/20189/mbox/",
    "series": [
        {
            "id": 4352,
            "url": "https://patchwork.libcamera.org/api/series/4352/?format=api",
            "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=4352",
            "date": "2024-06-03T11:12:56",
            "name": "libcamera: dma_buffer_allocator: Add support for using udmabuf to alloc dma-buffers",
            "version": 3,
            "mbox": "https://patchwork.libcamera.org/series/4352/mbox/"
        }
    ],
    "comments": "https://patchwork.libcamera.org/api/patches/20189/comments/",
    "check": "pending",
    "checks": "https://patchwork.libcamera.org/api/patches/20189/checks/",
    "tags": {},
    "headers": {
        "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>",
        "X-Original-To": "parsemail@patchwork.libcamera.org",
        "Delivered-To": "parsemail@patchwork.libcamera.org",
        "Received": [
            "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id D173FC32C8\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon,  3 Jun 2024 11:13:13 +0000 (UTC)",
            "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 53F2B634D6;\n\tMon,  3 Jun 2024 13:13:13 +0200 (CEST)",
            "from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E1177634D3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  3 Jun 2024 13:13:09 +0200 (CEST)",
            "from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com\n\t[66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-65-ZIPH7nT1MiWRJ4EaowJjfQ-1; Mon, 03 Jun 2024 07:13:04 -0400",
            "from smtp.corp.redhat.com\n\t(int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\tkey-exchange X25519 server-signature RSA-PSS (2048 bits)\n\tserver-digest SHA256) (No client certificate requested)\n\tby mimecast-mx02.redhat.com (Postfix) with ESMTPS id D4C7E185A783;\n\tMon,  3 Jun 2024 11:13:03 +0000 (UTC)",
            "from x1.localdomain.com (unknown [10.39.193.39])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id D4D362875;\n\tMon,  3 Jun 2024 11:13:02 +0000 (UTC)"
        ],
        "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"fRAIVZx3\"; dkim-atps=neutral",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1717413188;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tcontent-transfer-encoding:content-transfer-encoding:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=7fWiu9w6PDuNO+txmZSsWbK8NOC1xAqGZAHpnpk1rCQ=;\n\tb=fRAIVZx3ywJEZj8pMFLS3pt/Gwz39JNj9+a34H4NOcR0IbA6u76s9AnfhsnHMvQaIq6tPd\n\t7j5y4y896Zgy7/2FimiZgzOTay9omL1PEmWIi4051GoU4sxyQeqHtyHz8xJ1I7AKLbceGe\n\tvwJddXmXM0fDx9K+gX3DCm82wnSBy44=",
        "X-MC-Unique": "ZIPH7nT1MiWRJ4EaowJjfQ-1",
        "From": "Hans de Goede <hdegoede@redhat.com>",
        "To": "libcamera-devel@lists.libcamera.org",
        "Cc": "Maxime Ripard <mripard@redhat.com>, Milan Zamazal <mzamazal@redhat.com>, \n\tHans de Goede <hdegoede@redhat.com>,\n\tHarvey Yang <chenghaoyang@chromium.org>,\n\tKieran Bingham <kieran.bingham@ideasonboard.com>,\n\tBryan O'Donoghue <bryan.odonoghue@linaro.org>,\n\tLaurent Pinchart <laurent.pinchart@ideasonboard.com>",
        "Subject": "[PATCH v3 2/3] libcamera: DmaBufAllocator: Support allocating from\n\t/dev/udmabuf",
        "Date": "Mon,  3 Jun 2024 13:12:58 +0200",
        "Message-ID": "<20240603111259.54321-3-hdegoede@redhat.com>",
        "In-Reply-To": "<20240603111259.54321-1-hdegoede@redhat.com>",
        "References": "<20240603111259.54321-1-hdegoede@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.4.1 on 10.11.54.5",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "X-BeenThere": "libcamera-devel@lists.libcamera.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "<libcamera-devel.lists.libcamera.org>",
        "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>",
        "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>",
        "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>",
        "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>",
        "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>",
        "Errors-To": "libcamera-devel-bounces@lists.libcamera.org",
        "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"
    },
    "content": "The dma-buf allocator currently allocates from CMA and system heaps.\n\nExtend the dma-buf allocator to support allocating dma-buffers by creating\nmemfd-s and turning those into dma-buffers using /dev/udmabuf.\n\nThe buffers allocated through memfd/udmabuf are not suitable for zero-copy\nbuffer sharing with other devices.\n\nCo-developed-by: Harvey Yang <chenghaoyang@chromium.org>\nSigned-off-by: Harvey Yang <chenghaoyang@chromium.org>\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\nTested-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org> # Lenovo-x13s\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\nSigned-off-by: Hans de Goede <hdegoede@redhat.com>\n---\nChanges in v3:\n- Style fixes to some comments\n- Drop the unnecessary checking of the created dma-buf size\n\nChanges in v2:\n- Reword the commit message\n- Add a new DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf type for udmabuf\n- Drop unnecessary size != size check\n- Reword log messages to be more like the DMA heap alloc path\n- Move UniqueFD(ret) up so as to not leak the fd on errors\n---\n .../libcamera/internal/dma_buf_allocator.h    |   4 +\n src/libcamera/dma_buf_allocator.cpp           | 101 +++++++++++++++---\n 2 files changed, 90 insertions(+), 15 deletions(-)",
    "diff": "diff --git a/include/libcamera/internal/dma_buf_allocator.h b/include/libcamera/internal/dma_buf_allocator.h\nindex a881042e..36ec1696 100644\n--- a/include/libcamera/internal/dma_buf_allocator.h\n+++ b/include/libcamera/internal/dma_buf_allocator.h\n@@ -20,6 +20,7 @@ public:\n \tenum class DmaBufAllocatorFlag {\n \t\tCmaHeap = 1 << 0,\n \t\tSystemHeap = 1 << 1,\n+\t\tUDmaBuf = 1 << 2,\n \t};\n \n \tusing DmaBufAllocatorFlags = Flags<DmaBufAllocatorFlag>;\n@@ -30,7 +31,10 @@ public:\n \tUniqueFD alloc(const char *name, std::size_t size);\n \n private:\n+\tUniqueFD allocFromHeap(const char *name, std::size_t size);\n+\tUniqueFD allocFromUDmaBuf(const char *name, std::size_t size);\n \tUniqueFD providerHandle_;\n+\tDmaBufAllocatorFlag type_;\n };\n \n LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaBufAllocator::DmaBufAllocatorFlag)\ndiff --git a/src/libcamera/dma_buf_allocator.cpp b/src/libcamera/dma_buf_allocator.cpp\nindex af512512..5ae51721 100644\n--- a/src/libcamera/dma_buf_allocator.cpp\n+++ b/src/libcamera/dma_buf_allocator.cpp\n@@ -11,10 +11,14 @@\n #include <array>\n #include <fcntl.h>\n #include <sys/ioctl.h>\n+#include <sys/mman.h>\n+#include <sys/stat.h>\n+#include <sys/types.h>\n #include <unistd.h>\n \n #include <linux/dma-buf.h>\n #include <linux/dma-heap.h>\n+#include <linux/udmabuf.h>\n \n #include <libcamera/base/log.h>\n \n@@ -32,7 +36,7 @@ struct DmaBufAllocatorInfo {\n };\n #endif\n \n-static constexpr std::array<DmaBufAllocatorInfo, 3> providerInfos = { {\n+static constexpr std::array<DmaBufAllocatorInfo, 4> providerInfos = { {\n \t/*\n \t * /dev/dma_heap/linux,cma is the CMA dma-heap. When the cma heap size is\n \t * specified on the kernel command line, this gets renamed to \"reserved\".\n@@ -40,6 +44,7 @@ static constexpr std::array<DmaBufAllocatorInfo, 3> providerInfos = { {\n \t{ DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap, \"/dev/dma_heap/linux,cma\" },\n \t{ DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap, \"/dev/dma_heap/reserved\" },\n \t{ DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap, \"/dev/dma_heap/system\" },\n+\t{ DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf, \"/dev/udmabuf\" },\n } };\n \n LOG_DEFINE_CATEGORY(DmaBufAllocator)\n@@ -63,6 +68,8 @@ LOG_DEFINE_CATEGORY(DmaBufAllocator)\n  * \\brief Allocate from a CMA dma-heap, providing physically-contiguous memory\n  * \\var DmaBufAllocator::SystemHeap\n  * \\brief Allocate from the system dma-heap, using the page allocator\n+ * \\var DmaBufAllocator::UDmaBuf\n+ * \\brief Allocate using a memfd + /dev/udmabuf\n  */\n \n /**\n@@ -100,6 +107,7 @@ DmaBufAllocator::DmaBufAllocator(DmaBufAllocatorFlags type)\n \n \t\tLOG(DmaBufAllocator, Debug) << \"Using \" << info.deviceNodeName;\n \t\tproviderHandle_ = UniqueFD(ret);\n+\t\ttype_ = info.type;\n \t\tbreak;\n \t}\n \n@@ -118,25 +126,66 @@ DmaBufAllocator::~DmaBufAllocator() = default;\n  * \\return True if the DmaBufAllocator is valid, false otherwise\n  */\n \n-/**\n- * \\brief Allocate a dma-buf from the DmaBufAllocator\n- * \\param [in] name The name to set for the allocated buffer\n- * \\param [in] size The size of the buffer to allocate\n- *\n- * Allocates a dma-buf with read/write access.\n- *\n- * If the allocation fails, return an invalid UniqueFD.\n- *\n- * \\return The UniqueFD of the allocated buffer\n- */\n-UniqueFD DmaBufAllocator::alloc(const char *name, std::size_t size)\n+UniqueFD DmaBufAllocator::allocFromUDmaBuf(const char *name, std::size_t size)\n {\n-\tint ret;\n+\t/* Size must be a multiple of the page size. Round it up. */\n+\tstd::size_t pageMask = sysconf(_SC_PAGESIZE) - 1;\n+\tsize = (size + pageMask) & ~pageMask;\n \n-\tif (!name)\n+\tint ret = memfd_create(name, MFD_ALLOW_SEALING);\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(DmaBufAllocator, Error)\n+\t\t\t<< \"Failed to allocate memfd storage for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n \t\treturn {};\n+\t}\n \n+\tUniqueFD memfd(ret);\n+\n+\tret = ftruncate(memfd.get(), size);\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(DmaBufAllocator, Error)\n+\t\t\t<< \"Failed to set memfd size for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n+\t\treturn {};\n+\t}\n+\n+\t/* udmabuf dma-buffers *must* have the F_SEAL_SHRINK seal. */\n+\tret = fcntl(memfd.get(), F_ADD_SEALS, F_SEAL_SHRINK);\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(DmaBufAllocator, Error)\n+\t\t\t<< \"Failed to seal the memfd for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n+\t\treturn {};\n+\t}\n+\n+\tstruct udmabuf_create create;\n+\n+\tcreate.memfd = memfd.get();\n+\tcreate.flags = UDMABUF_FLAGS_CLOEXEC;\n+\tcreate.offset = 0;\n+\tcreate.size = size;\n+\n+\tret = ::ioctl(providerHandle_.get(), UDMABUF_CREATE, &create);\n+\tif (ret < 0) {\n+\t\tret = errno;\n+\t\tLOG(DmaBufAllocator, Error)\n+\t\t\t<< \"Failed to create dma buf for \" << name\n+\t\t\t<< \": \" << strerror(ret);\n+\t\treturn {};\n+\t}\n+\n+\t/* The underlying memfd is kept as as a reference in the kernel. */\n+\treturn UniqueFD(ret);\n+}\n+\n+UniqueFD DmaBufAllocator::allocFromHeap(const char *name, std::size_t size)\n+{\n \tstruct dma_heap_allocation_data alloc = {};\n+\tint ret;\n \n \talloc.len = size;\n \talloc.fd_flags = O_CLOEXEC | O_RDWR;\n@@ -159,4 +208,26 @@ UniqueFD DmaBufAllocator::alloc(const char *name, std::size_t size)\n \treturn allocFd;\n }\n \n+/**\n+ * \\brief Allocate a dma-buf from the DmaBufAllocator\n+ * \\param [in] name The name to set for the allocated buffer\n+ * \\param [in] size The size of the buffer to allocate\n+ *\n+ * Allocates a dma-buf with read/write access.\n+ *\n+ * If the allocation fails, return an invalid UniqueFD.\n+ *\n+ * \\return The UniqueFD of the allocated buffer\n+ */\n+UniqueFD DmaBufAllocator::alloc(const char *name, std::size_t size)\n+{\n+\tif (!name)\n+\t\treturn {};\n+\n+\tif (type_ == DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)\n+\t\treturn allocFromUDmaBuf(name, size);\n+\telse\n+\t\treturn allocFromHeap(name, size);\n+}\n+\n } /* namespace libcamera */\n",
    "prefixes": [
        "v3",
        "2/3"
    ]
}