Skip to content

Commit 39482d5

Browse files
HarveyCHYangkbingham
authored andcommitted
DmaBufAllocator: Add Dma Buffer synchronization function & helper class
To synchronize CPU access with mmap and hardware access on DMA buffers, using `DMA_BUF_IOCTL_SYNC` is required. This patch adds a function and a helper class to allow users to sync buffers more easily. Signed-off-by: Han-Lin Chen <hanlinchen@chromium.org> Co-developed-by: Harvey Yang <chenghaoyang@chromium.org> Signed-off-by: Harvey Yang <chenghaoyang@chromium.org> Reviewed-by: Milan Zamazal <mzamazal@redhat.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
1 parent 562b633 commit 39482d5

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

include/libcamera/internal/dma_buf_allocator.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <vector>
1313

1414
#include <libcamera/base/flags.h>
15+
#include <libcamera/base/shared_fd.h>
1516
#include <libcamera/base/unique_fd.h>
1617

1718
namespace libcamera {
@@ -48,6 +49,26 @@ class DmaBufAllocator
4849
DmaBufAllocatorFlag type_;
4950
};
5051

52+
class DmaSyncer final
53+
{
54+
public:
55+
enum class SyncType {
56+
Read = 0,
57+
Write,
58+
ReadWrite,
59+
};
60+
61+
explicit DmaSyncer(SharedFD fd, SyncType type = SyncType::ReadWrite);
62+
63+
~DmaSyncer();
64+
65+
private:
66+
void sync(uint64_t step);
67+
68+
SharedFD fd_;
69+
uint64_t flags_ = 0;
70+
};
71+
5172
LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaBufAllocator::DmaBufAllocatorFlag)
5273

5374
} /* namespace libcamera */

src/libcamera/dma_buf_allocator.cpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,78 @@ DmaBufAllocator::createBuffer(std::string name,
262262
return std::make_unique<FrameBuffer>(planes);
263263
}
264264

265+
/**
266+
* \class DmaSyncer
267+
* \brief Helper class for dma-buf's synchronization
268+
*
269+
* This class wraps a userspace dma-buf's synchronization process with an
270+
* object's lifetime.
271+
*
272+
* It's used when the user needs to access a dma-buf with CPU, mostly mapped
273+
* with MappedFrameBuffer, so that the buffer is synchronized between CPU and
274+
* ISP.
275+
*/
276+
277+
/**
278+
* \enum DmaSyncer::SyncType
279+
* \brief Read and/or write access via the CPU map
280+
* \var DmaSyncer::Read
281+
* \brief Indicates that the mapped dma-buf will be read by the client via the
282+
* CPU map
283+
* \var DmaSyncer::Write
284+
* \brief Indicates that the mapped dm-buf will be written by the client via the
285+
* CPU map
286+
* \var DmaSyncer::ReadWrite
287+
* \brief Indicates that the mapped dma-buf will be read and written by the
288+
* client via the CPU map
289+
*/
290+
291+
/**
292+
* \brief Construct a DmaSyncer with a dma-buf's fd and the access type
293+
* \param[in] fd The dma-buf's file descriptor to synchronize
294+
* \param[in] type Read and/or write access via the CPU map
295+
*/
296+
DmaSyncer::DmaSyncer(SharedFD fd, SyncType type)
297+
: fd_(fd)
298+
{
299+
switch (type) {
300+
case SyncType::Read:
301+
flags_ = DMA_BUF_SYNC_READ;
302+
break;
303+
case SyncType::Write:
304+
flags_ = DMA_BUF_SYNC_WRITE;
305+
break;
306+
case SyncType::ReadWrite:
307+
flags_ = DMA_BUF_SYNC_RW;
308+
break;
309+
}
310+
311+
sync(DMA_BUF_SYNC_START);
312+
}
313+
314+
DmaSyncer::~DmaSyncer()
315+
{
316+
sync(DMA_BUF_SYNC_END);
317+
}
318+
319+
void DmaSyncer::sync(uint64_t step)
320+
{
321+
struct dma_buf_sync sync = {
322+
.flags = flags_ | step
323+
};
324+
325+
int ret;
326+
do {
327+
ret = ioctl(fd_.get(), DMA_BUF_IOCTL_SYNC, &sync);
328+
} while (ret && (errno == EINTR || errno == EAGAIN));
329+
330+
if (ret) {
331+
ret = errno;
332+
LOG(DmaBufAllocator, Error)
333+
<< "Unable to sync dma fd: " << fd_.get()
334+
<< ", err: " << strerror(ret)
335+
<< ", flags: " << sync.flags;
336+
}
337+
}
338+
265339
} /* namespace libcamera */

0 commit comments

Comments
 (0)