@@ -33,6 +33,9 @@ file structure:
::
configuration:
+ dma_buf_allocator:
+ provider_priority:
+ - ... # dma-buf provider name: cma, system, or udmabuf
ipa:
force_isolation: # true/false
config_paths:
@@ -62,6 +65,11 @@ Configuration file example
---
version: 1
configuration:
+ dma_buf_allocator:
+ provider_priority:
+ - udmabuf
+ - cma
+ - system
ipa:
config_paths:
- /home/user/.libcamera/share/ipa
@@ -150,6 +158,25 @@ LIBCAMERA_SOFTISP_MODE, software_isp.mode
Example value: ``gpu``
+dma_buf_allocator.provider_priority
+ Define an ordered list of dma-buf providers to try when libcamera
+ allocates buffers internally (for example for the software ISP). The
+ first requested provider that is available on the system is used. Valid
+ provider names are ``cma`` (CMA dma-heap), ``system`` (system dma-heap)
+ and ``udmabuf`` (memfd + /dev/udmabuf). Providers accepted by a component
+ but not listed here are tried after the listed ones, in libcamera's
+ built-in order.
+
+ Example value:
+
+ ::
+
+ dma_buf_allocator:
+ provider_priority:
+ - udmabuf
+ - cma
+ - system
+
pipelines.simple.supported_devices.driver, pipelines.simple.supported_devices.software_isp
Override whether software ISP is enabled for the given driver.
@@ -18,6 +18,7 @@
namespace libcamera {
+class CameraManager;
class FrameBuffer;
class DmaBufAllocator
@@ -31,7 +32,8 @@ public:
using DmaBufAllocatorFlags = Flags<DmaBufAllocatorFlag>;
- DmaBufAllocator(DmaBufAllocatorFlags flags = DmaBufAllocatorFlag::CmaHeap);
+ DmaBufAllocator(const CameraManager &cm,
+ DmaBufAllocatorFlags type = DmaBufAllocatorFlag::CmaHeap);
~DmaBufAllocator();
bool isValid() const { return providerHandle_.isValid(); }
UniqueFD alloc(const char *name, std::size_t size);
@@ -8,13 +8,16 @@
#include "libcamera/internal/dma_buf_allocator.h"
+#include <algorithm>
#include <array>
#include <fcntl.h>
+#include <optional>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
+#include <vector>
#include <linux/dma-buf.h>
#include <linux/dma-heap.h>
@@ -26,6 +29,8 @@
#include <libcamera/framebuffer.h>
+#include "libcamera/internal/camera_manager.h"
+
/**
* \file dma_buf_allocator.cpp
* \brief dma-buf allocator
@@ -51,6 +56,26 @@ static constexpr std::array<DmaBufAllocatorInfo, 4> providerInfos = { {
{ DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf, "/dev/udmabuf" },
} };
+/* Built-in provider priority, used when no other order is specified. */
+static constexpr std::array<DmaBufAllocator::DmaBufAllocatorFlag, 3>
+ defaultProviderPriority = { {
+ DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap,
+ DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap,
+ DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf,
+ } };
+
+static std::optional<DmaBufAllocator::DmaBufAllocatorFlag>
+providerFromName(const std::string &name)
+{
+ if (name == "cma")
+ return DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap;
+ if (name == "system")
+ return DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap;
+ if (name == "udmabuf")
+ return DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf;
+ return {};
+}
+
LOG_DEFINE_CATEGORY(DmaBufAllocator)
/**
@@ -83,6 +108,7 @@ LOG_DEFINE_CATEGORY(DmaBufAllocator)
/**
* \brief Construct a DmaBufAllocator of a given type
+ * \param[in] cm The camera manager, used to access the global configuration
* \param[in] type The type(s) of the dma-buf providers to allocate from
*
* The dma-buf provider type is selected with the \a type parameter, which
@@ -90,29 +116,67 @@ LOG_DEFINE_CATEGORY(DmaBufAllocator)
* the constructed DmaBufAllocator instance is invalid as indicated by
* the isValid() function.
*
- * Multiple types can be selected by combining type flags, in which case
- * the constructed DmaBufAllocator will match one of the types. If multiple
- * requested types can work on the system, which provider is used is undefined.
+ * Multiple types can be selected by combining type flags. In that case the
+ * provider to use is chosen by priority: the providers listed in the
+ * `dma_buf_allocator.provider_priority` global configuration option (valid
+ * names are "cma", "system" and "udmabuf") take precedence, followed by
+ * libcamera's built-in order (CMA heap, system heap, then udmabuf). The first
+ * provider that is both requested and accessible is used.
*/
-DmaBufAllocator::DmaBufAllocator(DmaBufAllocatorFlags type)
+DmaBufAllocator::DmaBufAllocator(const CameraManager &cm, DmaBufAllocatorFlags type)
{
- for (const auto &info : providerInfos) {
- if (!(type & info.type))
- continue;
+ std::vector<DmaBufAllocatorFlag> priority;
+
+ /*
+ * The global configuration can override the provider priority;
+ * providers not listed are appended in the built-in order, so no
+ * acceptable provider is ever dropped.
+ */
+ const GlobalConfiguration &configuration = cm._d()->configuration();
+ const std::vector<std::string> providerPriority =
+ configuration.listOption({ "dma_buf_allocator", "provider_priority" })
+ .value_or(std::vector<std::string>{});
+
+ for (const std::string &name : providerPriority) {
+ auto flag = providerFromName(name);
+ if (flag)
+ priority.push_back(*flag);
+ else
+ LOG(DmaBufAllocator, Warning)
+ << "Ignoring unknown dma-buf provider \""
+ << name << "\"";
+ }
- int ret = ::open(info.deviceNodeName, O_RDONLY | O_CLOEXEC, 0);
- if (ret < 0) {
- ret = errno;
- LOG(DmaBufAllocator, Debug)
- << "Failed to open " << info.deviceNodeName << ": "
- << strerror(ret);
+ for (DmaBufAllocatorFlag flag : defaultProviderPriority) {
+ if (std::find(priority.begin(), priority.end(), flag) == priority.end())
+ priority.push_back(flag);
+ }
+
+ for (DmaBufAllocatorFlag flag : priority) {
+ if (!(type & flag))
continue;
+
+ for (const auto &info : providerInfos) {
+ if (info.type != flag)
+ continue;
+
+ int ret = ::open(info.deviceNodeName, O_RDONLY | O_CLOEXEC, 0);
+ if (ret < 0) {
+ ret = errno;
+ LOG(DmaBufAllocator, Debug)
+ << "Failed to open " << info.deviceNodeName
+ << ": " << strerror(ret);
+ continue;
+ }
+
+ LOG(DmaBufAllocator, Debug) << "Using " << info.deviceNodeName;
+ providerHandle_ = UniqueFD(ret);
+ type_ = info.type;
+ break;
}
- LOG(DmaBufAllocator, Debug) << "Using " << info.deviceNodeName;
- providerHandle_ = UniqueFD(ret);
- type_ = info.type;
- break;
+ if (providerHandle_.isValid())
+ break;
}
if (!providerHandle_.isValid())
@@ -39,7 +39,7 @@ class Vc4CameraData final : public RPi::CameraData
{
public:
Vc4CameraData(PipelineHandler *pipe)
- : RPi::CameraData(pipe)
+ : RPi::CameraData(pipe), dmaHeap_(*pipe->cameraManager())
{
}
@@ -238,9 +238,10 @@ bool PipelineHandlerVirtual::created_ = false;
PipelineHandlerVirtual::PipelineHandlerVirtual(CameraManager *manager)
: PipelineHandler(manager),
- dmaBufAllocator_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
- DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
- DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
+ dmaBufAllocator_(*manager,
+ DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
+ DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
+ DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
{
}
@@ -24,6 +24,7 @@
#include <libcamera/stream.h>
#include "libcamera/internal/bayer_format.h"
+#include "libcamera/internal/camera_manager.h"
#include "libcamera/internal/framebuffer.h"
#include "libcamera/internal/software_isp/debayer_params.h"
@@ -81,9 +82,10 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
ControlInfoMap *ipaControls)
: ispWorkerThread_("SWIspWorker"),
- dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
- DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
- DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
+ dmaHeap_(*pipe->cameraManager(),
+ DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
+ DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
+ DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
{
if (!dmaHeap_.isValid()) {
LOG(SoftwareIsp, Error) << "Failed to create DmaBufAllocator object";
DmaBufAllocator selects a provider using a fixed priority (CMA heap, system heap, then udmabuf) and picks the first one that can be opened. On platforms with a small CMA region this is suboptimal: CMA is always chosen when present even though it may be too small, while udmabuf, backed by pageable system memory, would work. Make the provider priority order configurable through the 'dma_buf_allocator/provider_priority' global configuration option, an ordered list of preferred provider names. Providers not listed are tried afterwards in the built-in order (CMA heap, system heap, then udmabuf). When the option is absent the historical order is kept, so behaviour is unchanged by default. DmaBufAllocator reads this option itself. Its constructor now takes a CameraManager reference to reach the GlobalConfiguration, following the same pattern as the other software ISP helpers (SwStatsCpu, Benchmark, Debayer). The callers only pass the camera manager and the providers they accept, rather than parsing the configuration themselves. This lets a platform prefer udmabuf by shipping a configuration.yaml. The set of providers stays limited to what the caller requested, so a component that requires physically-contiguous memory (CMA only) is not given a udmabuf-backed buffer. Document the new option in runtime_configuration.rst. Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- Changes in v2: - Move the configuration parsing from the callers into DmaBufAllocator's constructor. The constructor now takes a 'const CameraManager &cm' argument to reach the GlobalConfiguration and reads 'dma_buf_allocator/provider_priority' itself, so the callers no longer parse the config file. (Hans) - Update the DmaBufAllocator callers (software ISP, virtual pipeline and rpi/vc4) to the new constructor signature. - Drop the "This is useful on platforms with a small CMA region..." sentence from runtime_configuration.rst; the rationale is kept in the commit message only. (Hans) - Reword the commit message to describe reading the option inside DmaBufAllocator rather than in each caller. - Link to v1: https://lists.libcamera.org/pipermail/libcamera-devel/2026-September/062007.html --- Documentation/runtime_configuration.rst | 27 +++++++ include/libcamera/internal/dma_buf_allocator.h | 4 +- src/libcamera/dma_buf_allocator.cpp | 98 +++++++++++++++++++++----- src/libcamera/pipeline/rpi/vc4/vc4.cpp | 2 +- src/libcamera/pipeline/virtual/virtual.cpp | 7 +- src/libcamera/software_isp/software_isp.cpp | 8 ++- 6 files changed, 121 insertions(+), 25 deletions(-) --- base-commit: 87c7285663aaad7608fdc18d5216ec6811c685c7 change-id: 20260911-udma-a002f890212c Best regards,