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>
This commit is contained in:
parent
562b6335d9
commit
39482d59fe
2 changed files with 95 additions and 0 deletions
|
@ -12,6 +12,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <libcamera/base/flags.h>
|
#include <libcamera/base/flags.h>
|
||||||
|
#include <libcamera/base/shared_fd.h>
|
||||||
#include <libcamera/base/unique_fd.h>
|
#include <libcamera/base/unique_fd.h>
|
||||||
|
|
||||||
namespace libcamera {
|
namespace libcamera {
|
||||||
|
@ -48,6 +49,26 @@ private:
|
||||||
DmaBufAllocatorFlag type_;
|
DmaBufAllocatorFlag type_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DmaSyncer final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class SyncType {
|
||||||
|
Read = 0,
|
||||||
|
Write,
|
||||||
|
ReadWrite,
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit DmaSyncer(SharedFD fd, SyncType type = SyncType::ReadWrite);
|
||||||
|
|
||||||
|
~DmaSyncer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void sync(uint64_t step);
|
||||||
|
|
||||||
|
SharedFD fd_;
|
||||||
|
uint64_t flags_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaBufAllocator::DmaBufAllocatorFlag)
|
LIBCAMERA_FLAGS_ENABLE_OPERATORS(DmaBufAllocator::DmaBufAllocatorFlag)
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
|
@ -262,4 +262,78 @@ DmaBufAllocator::createBuffer(std::string name,
|
||||||
return std::make_unique<FrameBuffer>(planes);
|
return std::make_unique<FrameBuffer>(planes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class DmaSyncer
|
||||||
|
* \brief Helper class for dma-buf's synchronization
|
||||||
|
*
|
||||||
|
* This class wraps a userspace dma-buf's synchronization process with an
|
||||||
|
* object's lifetime.
|
||||||
|
*
|
||||||
|
* It's used when the user needs to access a dma-buf with CPU, mostly mapped
|
||||||
|
* with MappedFrameBuffer, so that the buffer is synchronized between CPU and
|
||||||
|
* ISP.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \enum DmaSyncer::SyncType
|
||||||
|
* \brief Read and/or write access via the CPU map
|
||||||
|
* \var DmaSyncer::Read
|
||||||
|
* \brief Indicates that the mapped dma-buf will be read by the client via the
|
||||||
|
* CPU map
|
||||||
|
* \var DmaSyncer::Write
|
||||||
|
* \brief Indicates that the mapped dm-buf will be written by the client via the
|
||||||
|
* CPU map
|
||||||
|
* \var DmaSyncer::ReadWrite
|
||||||
|
* \brief Indicates that the mapped dma-buf will be read and written by the
|
||||||
|
* client via the CPU map
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Construct a DmaSyncer with a dma-buf's fd and the access type
|
||||||
|
* \param[in] fd The dma-buf's file descriptor to synchronize
|
||||||
|
* \param[in] type Read and/or write access via the CPU map
|
||||||
|
*/
|
||||||
|
DmaSyncer::DmaSyncer(SharedFD fd, SyncType type)
|
||||||
|
: fd_(fd)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SyncType::Read:
|
||||||
|
flags_ = DMA_BUF_SYNC_READ;
|
||||||
|
break;
|
||||||
|
case SyncType::Write:
|
||||||
|
flags_ = DMA_BUF_SYNC_WRITE;
|
||||||
|
break;
|
||||||
|
case SyncType::ReadWrite:
|
||||||
|
flags_ = DMA_BUF_SYNC_RW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sync(DMA_BUF_SYNC_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
DmaSyncer::~DmaSyncer()
|
||||||
|
{
|
||||||
|
sync(DMA_BUF_SYNC_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DmaSyncer::sync(uint64_t step)
|
||||||
|
{
|
||||||
|
struct dma_buf_sync sync = {
|
||||||
|
.flags = flags_ | step
|
||||||
|
};
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = ioctl(fd_.get(), DMA_BUF_IOCTL_SYNC, &sync);
|
||||||
|
} while (ret && (errno == EINTR || errno == EAGAIN));
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
ret = errno;
|
||||||
|
LOG(DmaBufAllocator, Error)
|
||||||
|
<< "Unable to sync dma fd: " << fd_.get()
|
||||||
|
<< ", err: " << strerror(ret)
|
||||||
|
<< ", flags: " << sync.flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace libcamera */
|
} /* namespace libcamera */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue