[libcamera-devel] [PATCH v3 2/2] libcamera: pipeline: ipa: raspberrypi: Use dma heap allocs for LS tables

Naushir Patuck naush at raspberrypi.com
Fri Jul 17 08:22:19 CEST 2020


Hi Laurent,

Thank you for the changes.

On Fri, 17 Jul 2020 at 01:15, Laurent Pinchart
<laurent.pinchart at ideasonboard.com> wrote:
>
> From: Naushir Patuck <naush at raspberrypi.com>
>
> Remove use of vcsm allocations and replace with dma heap allocations.
> The pipeline handler now passes the fd of the allocation over to the IPA
> instead of the raw pointer.
>
> Also use libcamera::FileDescriptor for fd lifetime management.
>
> This commit must be built alongside the accompanying BCM2835 ISP kernel
> driver changes at https://github.com/raspberrypi/linux/pull/3715.
> Otherwise a mismatch will cause undefined behavior.
>
> Signed-off-by: Naushir Patuck <naush at raspberrypi.com>
> Reviewed-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>
> Signed-off-by: Laurent Pinchart <laurent.pinchart at ideasonboard.com>

Reviewed-by: Naushir Patuck <naush at raspberrypi.com>

> ---
>  include/linux/bcm2835-isp.h                   |   4 +-
>  include/linux/vc_sm_cma_ioctl.h               | 135 ----------------
>  src/ipa/raspberrypi/raspberrypi.cpp           |  28 +++-
>  .../pipeline/raspberrypi/dma_heaps.cpp        |  84 ++++++++++
>  .../pipeline/raspberrypi/dma_heaps.h          |  31 ++++
>  .../pipeline/raspberrypi/meson.build          |   1 +
>  .../pipeline/raspberrypi/raspberrypi.cpp      |  49 ++----
>  src/libcamera/pipeline/raspberrypi/vcsm.h     | 149 ------------------
>  8 files changed, 154 insertions(+), 327 deletions(-)
>  delete mode 100644 include/linux/vc_sm_cma_ioctl.h
>  create mode 100644 src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
>  create mode 100644 src/libcamera/pipeline/raspberrypi/dma_heaps.h
>  delete mode 100644 src/libcamera/pipeline/raspberrypi/vcsm.h
>
> diff --git a/include/linux/bcm2835-isp.h b/include/linux/bcm2835-isp.h
> index e7afc367fd76..45abb681517e 100644
> --- a/include/linux/bcm2835-isp.h
> +++ b/include/linux/bcm2835-isp.h
> @@ -108,7 +108,7 @@ enum bcm2835_isp_gain_format {
>   * @grid_stride:       Row to row distance (in grid cells) between grid cells
>   *                     in the same horizontal location.
>   * @grid_height:       Height of lens shading tables in grid cells.
> - * @mem_handle_table:  Memory handle to the tables.
> + * @dmabuf:            dmabuf file handle containing the table.
>   * @ref_transform:     Reference transform - unsupported, please pass zero.
>   * @corner_sampled:    Whether the gains are sampled at the corner points
>   *                     of the grid cells or in the cell centres.
> @@ -120,7 +120,7 @@ struct bcm2835_isp_lens_shading {
>         __u32 grid_width;
>         __u32 grid_stride;
>         __u32 grid_height;
> -       __u32 mem_handle_table;
> +       __s32 dmabuf;
>         __u32 ref_transform;
>         __u32 corner_sampled;
>         __u32 gain_format;
> diff --git a/include/linux/vc_sm_cma_ioctl.h b/include/linux/vc_sm_cma_ioctl.h
> deleted file mode 100644
> index 21b8758ea03f..000000000000
> --- a/include/linux/vc_sm_cma_ioctl.h
> +++ /dev/null
> @@ -1,135 +0,0 @@
> -/*
> -Copyright (c) 2012, Broadcom Europe Ltd
> -All rights reserved.
> -
> -Redistribution and use in source and binary forms, with or without
> -modification, are permitted provided that the following conditions are met:
> -    * Redistributions of source code must retain the above copyright
> -      notice, this list of conditions and the following disclaimer.
> -    * Redistributions in binary form must reproduce the above copyright
> -      notice, this list of conditions and the following disclaimer in the
> -      documentation and/or other materials provided with the distribution.
> -    * Neither the name of the copyright holder nor the
> -      names of its contributors may be used to endorse or promote products
> -      derived from this software without specific prior written permission.
> -
> -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
> -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
> -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
> -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
> -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
> -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> -*/
> -
> -/*
> - * Copyright 2019 Raspberry Pi (Trading) Ltd.  All rights reserved.
> - *
> - * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
> - */
> -
> -#ifndef __VC_SM_CMA_IOCTL_H
> -#define __VC_SM_CMA_IOCTL_H
> -
> -/* ---- Include Files ---------------------------------------------------- */
> -
> -#include <linux/types.h>       /* Needed for standard types */
> -
> -#include <linux/ioctl.h>
> -
> -/* ---- Constants and Types ---------------------------------------------- */
> -
> -#define VC_SM_CMA_RESOURCE_NAME               32
> -#define VC_SM_CMA_RESOURCE_NAME_DEFAULT       "sm-host-resource"
> -
> -/* Type define used to create unique IOCTL number */
> -#define VC_SM_CMA_MAGIC_TYPE                  'J'
> -
> -/* IOCTL commands on /dev/vc-sm-cma */
> -enum vc_sm_cma_cmd_e {
> -       VC_SM_CMA_CMD_ALLOC = 0x5A,     /* Start at 0x5A arbitrarily */
> -
> -       VC_SM_CMA_CMD_IMPORT_DMABUF,
> -
> -       VC_SM_CMA_CMD_CLEAN_INVALID2,
> -
> -       VC_SM_CMA_CMD_LAST      /* Do not delete */
> -};
> -
> -/* Cache type supported, conveniently matches the user space definition in
> - * user-vcsm.h.
> - */
> -enum vc_sm_cma_cache_e {
> -       VC_SM_CMA_CACHE_NONE,
> -       VC_SM_CMA_CACHE_HOST,
> -       VC_SM_CMA_CACHE_VC,
> -       VC_SM_CMA_CACHE_BOTH,
> -};
> -
> -/* IOCTL Data structures */
> -struct vc_sm_cma_ioctl_alloc {
> -       /* user -> kernel */
> -       __u32 size;
> -       __u32 num;
> -       __u32 cached;           /* enum vc_sm_cma_cache_e */
> -       __u32 pad;
> -       __u8 name[VC_SM_CMA_RESOURCE_NAME];
> -
> -       /* kernel -> user */
> -       __s32 handle;
> -       __u32 vc_handle;
> -       __u64 dma_addr;
> -};
> -
> -struct vc_sm_cma_ioctl_import_dmabuf {
> -       /* user -> kernel */
> -       __s32 dmabuf_fd;
> -       __u32 cached;           /* enum vc_sm_cma_cache_e */
> -       __u8 name[VC_SM_CMA_RESOURCE_NAME];
> -
> -       /* kernel -> user */
> -       __s32 handle;
> -       __u32 vc_handle;
> -       __u32 size;
> -       __u32 pad;
> -       __u64 dma_addr;
> -};
> -
> -/*
> - * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
> - * invalidate_mode.
> - */
> -#define VC_SM_CACHE_OP_NOP       0x00
> -#define VC_SM_CACHE_OP_INV       0x01
> -#define VC_SM_CACHE_OP_CLEAN     0x02
> -#define VC_SM_CACHE_OP_FLUSH     0x03
> -
> -struct vc_sm_cma_ioctl_clean_invalid2 {
> -       __u32 op_count;
> -       __u32 pad;
> -       struct vc_sm_cma_ioctl_clean_invalid_block {
> -               __u32 invalidate_mode;
> -               __u32 block_count;
> -               void *  /*__user */start_address;
> -               __u32 block_size;
> -               __u32 inter_block_stride;
> -       } s[0];
> -};
> -
> -/* IOCTL numbers */
> -#define VC_SM_CMA_IOCTL_MEM_ALLOC\
> -       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
> -        struct vc_sm_cma_ioctl_alloc)
> -
> -#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
> -       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
> -        struct vc_sm_cma_ioctl_import_dmabuf)
> -
> -#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
> -       _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
> -        struct vc_sm_cma_ioctl_clean_invalid2)
> -
> -#endif /* __VC_SM_CMA_IOCTL_H */
> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp
> index 2fcbc782f8b8..7bd0488089e8 100644
> --- a/src/ipa/raspberrypi/raspberrypi.cpp
> +++ b/src/ipa/raspberrypi/raspberrypi.cpp
> @@ -15,6 +15,7 @@
>  #include <libcamera/buffer.h>
>  #include <libcamera/control_ids.h>
>  #include <libcamera/controls.h>
> +#include <libcamera/file_descriptor.h>
>  #include <libcamera/ipa/ipa_interface.h>
>  #include <libcamera/ipa/ipa_module_info.h>
>  #include <libcamera/ipa/raspberrypi.h>
> @@ -65,12 +66,14 @@ public:
>         IPARPi()
>                 : lastMode_({}), controller_(), controllerInit_(false),
>                   frame_count_(0), check_count_(0), hide_count_(0),
> -                 mistrust_count_(0), lsTableHandle_(0), lsTable_(nullptr)
> +                 mistrust_count_(0), lsTable_(nullptr)
>         {
>         }
>
>         ~IPARPi()
>         {
> +               if (lsTable_)
> +                       munmap(lsTable_, MAX_LS_GRID_SIZE);
>         }
>
>         int init(const IPASettings &settings) override;
> @@ -139,7 +142,7 @@ private:
>         /* How many frames we should avoid running control algos on. */
>         unsigned int mistrust_count_;
>         /* LS table allocation passed in from the pipeline handler. */
> -       uint32_t lsTableHandle_;
> +       FileDescriptor lsTableHandle_;
>         void *lsTable_;
>  };
>
> @@ -280,8 +283,23 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,
>
>         /* Store the lens shading table pointer and handle if available. */
>         if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {
> -               lsTable_ = reinterpret_cast<void *>(ipaConfig.data[0]);
> -               lsTableHandle_ = ipaConfig.data[1];
> +               /* Remove any previous table, if there was one. */
> +               if (lsTable_) {
> +                       munmap(lsTable_, MAX_LS_GRID_SIZE);
> +                       lsTable_ = nullptr;
> +               }
> +
> +               /* Map the LS table buffer into user space. */
> +               lsTableHandle_ = FileDescriptor(ipaConfig.data[0]);
> +               if (lsTableHandle_.isValid()) {
> +                       lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,
> +                                       MAP_SHARED, lsTableHandle_.fd(), 0);
> +
> +                       if (lsTable_ == MAP_FAILED) {
> +                               LOG(IPARPI, Error) << "dmaHeap mmap failure for LS table.";
> +                               lsTable_ = nullptr;
> +                       }
> +               }
>         }
>  }
>
> @@ -1030,7 +1048,7 @@ void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls)
>                 .grid_width = w,
>                 .grid_stride = w,
>                 .grid_height = h,
> -               .mem_handle_table = lsTableHandle_,
> +               .dmabuf = lsTableHandle_.fd(),
>                 .ref_transform = 0,
>                 .corner_sampled = 1,
>                 .gain_format = GAIN_FORMAT_U4P10
> diff --git a/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
> new file mode 100644
> index 000000000000..6769c04640f1
> --- /dev/null
> +++ b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
> @@ -0,0 +1,84 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> + *
> + * dma_heaps.h - Helper class for dma-heap allocations.
> + */
> +
> +#include "dma_heaps.h"
> +
> +#include <fcntl.h>
> +#include <linux/dma-buf.h>
> +#include <linux/dma-heap.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +
> +#include "libcamera/internal/log.h"
> +
> +/*
> + * /dev/dma-heap/linux,cma is the dma-heap allocator, which allows dmaheap-cma
> + * to only have to worry about importing.
> + *
> + * Annoyingly, should the cma heap size be specified on the kernel command line
> + * instead of DT, the heap gets named "reserved" instead.
> + */
> +#define DMA_HEAP_CMA_NAME "/dev/dma_heap/linux,cma"
> +#define DMA_HEAP_CMA_ALT_NAME "/dev/dma_heap/reserved"
> +
> +namespace libcamera {
> +
> +LOG_DECLARE_CATEGORY(RPI)
> +
> +namespace RPi {
> +
> +DmaHeap::DmaHeap()
> +{
> +       dmaHeapHandle_ = ::open(DMA_HEAP_CMA_NAME, O_RDWR, 0);
> +       if (dmaHeapHandle_ == -1) {
> +               dmaHeapHandle_ = ::open(DMA_HEAP_CMA_ALT_NAME, O_RDWR, 0);
> +               if (dmaHeapHandle_ == -1) {
> +                       LOG(RPI, Error) << "Could not open dmaHeap device";
> +               }
> +       }
> +}
> +
> +DmaHeap::~DmaHeap()
> +{
> +       if (dmaHeapHandle_)
> +               ::close(dmaHeapHandle_);
> +}
> +
> +FileDescriptor DmaHeap::alloc(const char *name, std::size_t size)
> +{
> +       int ret;
> +
> +       if (!name)
> +               return FileDescriptor();
> +
> +       struct dma_heap_allocation_data alloc = {};
> +
> +       alloc.len = size;
> +       alloc.fd_flags = O_CLOEXEC | O_RDWR;
> +
> +       ret = ::ioctl(dmaHeapHandle_, DMA_HEAP_IOCTL_ALLOC, &alloc);
> +
> +       if (ret < 0) {
> +               LOG(RPI, Error) << "dmaHeap allocation failure for "
> +                               << name;
> +               return FileDescriptor();
> +       }
> +
> +       ret = ::ioctl(alloc.fd, DMA_BUF_SET_NAME, name);
> +       if (ret < 0) {
> +               LOG(RPI, Error) << "dmaHeap naming failure for "
> +                               << name;
> +               ::close(alloc.fd);
> +               return FileDescriptor();
> +       }
> +
> +       return FileDescriptor(std::move(alloc.fd));
> +}
> +
> +} /* namespace RPi */
> +
> +} /* namespace libcamera */
> diff --git a/src/libcamera/pipeline/raspberrypi/dma_heaps.h b/src/libcamera/pipeline/raspberrypi/dma_heaps.h
> new file mode 100644
> index 000000000000..ae6be1135f17
> --- /dev/null
> +++ b/src/libcamera/pipeline/raspberrypi/dma_heaps.h
> @@ -0,0 +1,31 @@
> +/* SPDX-License-Identifier: LGPL-2.1-or-later */
> +/*
> + * Copyright (C) 2020, Raspberry Pi (Trading) Limited
> + *
> + * dma_heaps.h - Helper class for dma-heap allocations.
> + */
> +#ifndef __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__
> +#define __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__
> +
> +#include <libcamera/file_descriptor.h>
> +
> +namespace libcamera {
> +
> +namespace RPi {
> +
> +class DmaHeap
> +{
> +public:
> +       DmaHeap();
> +       ~DmaHeap();
> +       FileDescriptor alloc(const char *name, std::size_t size);
> +
> +private:
> +       int dmaHeapHandle_;
> +};
> +
> +} /* namespace RPi */
> +
> +} /* namespace libcamera */
> +
> +#endif /* __LIBCAMERA_PIPELINE_RASPBERRYPI_DMA_HEAPS_H__ */
> diff --git a/src/libcamera/pipeline/raspberrypi/meson.build b/src/libcamera/pipeline/raspberrypi/meson.build
> index dcfe07c5b720..ae0aed3b5234 100644
> --- a/src/libcamera/pipeline/raspberrypi/meson.build
> +++ b/src/libcamera/pipeline/raspberrypi/meson.build
> @@ -1,6 +1,7 @@
>  # SPDX-License-Identifier: CC0-1.0
>
>  libcamera_sources += files([
> +    'dma_heaps.cpp',
>      'raspberrypi.cpp',
>      'staggered_ctrl.cpp',
>  ])
> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> index 718749af5a6e..bf1c77144f85 100644
> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp
> @@ -13,6 +13,7 @@
>
>  #include <libcamera/camera.h>
>  #include <libcamera/control_ids.h>
> +#include <libcamera/file_descriptor.h>
>  #include <libcamera/formats.h>
>  #include <libcamera/ipa/raspberrypi.h>
>  #include <libcamera/logging.h>
> @@ -31,8 +32,8 @@
>  #include "libcamera/internal/v4l2_controls.h"
>  #include "libcamera/internal/v4l2_videodevice.h"
>
> +#include "dma_heaps.h"
>  #include "staggered_ctrl.h"
> -#include "vcsm.h"
>
>  namespace libcamera {
>
> @@ -286,24 +287,11 @@ class RPiCameraData : public CameraData
>  {
>  public:
>         RPiCameraData(PipelineHandler *pipe)
> -               : CameraData(pipe), sensor_(nullptr), lsTable_(nullptr),
> -                 state_(State::Stopped), dropFrame_(false), ispOutputCount_(0)
> +               : CameraData(pipe), sensor_(nullptr), state_(State::Stopped),
> +                 dropFrame_(false), ispOutputCount_(0)
>         {
>         }
>
> -       ~RPiCameraData()
> -       {
> -               /*
> -                * Free the LS table if we have allocated one. Another
> -                * allocation will occur in applyLS() with the appropriate
> -                * size.
> -                */
> -               if (lsTable_) {
> -                       vcsm_.free(lsTable_);
> -                       lsTable_ = nullptr;
> -               }
> -       }
> -
>         void frameStarted(uint32_t sequence);
>
>         int loadIPA();
> @@ -329,9 +317,9 @@ public:
>         /* Buffers passed to the IPA. */
>         std::vector<IPABuffer> ipaBuffers_;
>
> -       /* VCSM allocation helper. */
> -       ::RPi::Vcsm vcsm_;
> -       void *lsTable_;
> +       /* DMAHEAP allocation helper. */
> +       RPi::DmaHeap dmaHeap_;
> +       FileDescriptor lsTable_;
>
>         RPi::StaggeredCtrl staggeredCtrl_;
>         uint32_t expectedSequence_;
> @@ -1142,26 +1130,15 @@ int RPiCameraData::configureIPA()
>         entityControls.emplace(0, unicam_[Unicam::Image].dev()->controls());
>         entityControls.emplace(1, isp_[Isp::Input].dev()->controls());
>
> -       /* Allocate the lens shading table via vcsm and pass to the IPA. */
> -       if (!lsTable_) {
> -               lsTable_ = vcsm_.alloc("ls_grid", MAX_LS_GRID_SIZE);
> -               uintptr_t ptr = reinterpret_cast<uintptr_t>(lsTable_);
> -
> -               if (!lsTable_)
> +       /* Allocate the lens shading table via dmaHeap and pass to the IPA. */
> +       if (!lsTable_.isValid()) {
> +               lsTable_ = dmaHeap_.alloc("ls_grid", MAX_LS_GRID_SIZE);
> +               if (!lsTable_.isValid())
>                         return -ENOMEM;
>
> -               /*
> -                * The vcsm allocation will always be in the memory region
> -                * < 32-bits to allow Videocore to access the memory.
> -                *
> -                * \todo Sending a pointer to the IPA is a workaround for
> -                * vc_sm_cma not yet supporting dmabuf. This will not work with
> -                * IPA module isolation and should be reworked when vc_sma_cma
> -                * will permit.
> -                */
> +               /* Allow the IPA to mmap the LS table via the file descriptor. */
>                 ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;
> -               ipaConfig.data = { static_cast<uint32_t>(ptr & 0xffffffff),
> -                                  vcsm_.getVCHandle(lsTable_) };
> +               ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };
>         }
>
>         CameraSensorInfo sensorInfo = {};
> diff --git a/src/libcamera/pipeline/raspberrypi/vcsm.h b/src/libcamera/pipeline/raspberrypi/vcsm.h
> deleted file mode 100644
> index bebe86a76450..000000000000
> --- a/src/libcamera/pipeline/raspberrypi/vcsm.h
> +++ /dev/null
> @@ -1,149 +0,0 @@
> -/* SPDX-License-Identifier: LGPL-2.1-or-later */
> -/*
> - * Copyright (C) 2019, Raspberry Pi (Trading) Limited
> - *
> - * vcsm.h - Helper class for vcsm allocations.
> - */
> -#ifndef __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__
> -#define __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__
> -
> -#include <iostream>
> -#include <mutex>
> -
> -#include <fcntl.h>
> -#include <linux/vc_sm_cma_ioctl.h>
> -#include <sys/ioctl.h>
> -#include <sys/mman.h>
> -#include <unistd.h>
> -
> -namespace RPi {
> -
> -#define VCSM_CMA_DEVICE_NAME "/dev/vcsm-cma"
> -
> -class Vcsm
> -{
> -public:
> -       Vcsm()
> -       {
> -               vcsmHandle_ = ::open(VCSM_CMA_DEVICE_NAME, O_RDWR, 0);
> -               if (vcsmHandle_ == -1) {
> -                       std::cerr << "Could not open vcsm device: "
> -                                 << VCSM_CMA_DEVICE_NAME;
> -               }
> -       }
> -
> -       ~Vcsm()
> -       {
> -               /* Free all existing allocations. */
> -               auto it = allocMap_.begin();
> -               while (it != allocMap_.end())
> -                       it = remove(it->first);
> -
> -               if (vcsmHandle_)
> -                       ::close(vcsmHandle_);
> -       }
> -
> -       void *alloc(const char *name, unsigned int size,
> -                   vc_sm_cma_cache_e cache = VC_SM_CMA_CACHE_NONE)
> -       {
> -               unsigned int pageSize = getpagesize();
> -               void *user_ptr;
> -               int ret;
> -
> -               if (!name)
> -                       return nullptr;
> -
> -               /* Ask for page aligned allocation. */
> -               size = (size + pageSize - 1) & ~(pageSize - 1);
> -
> -               struct vc_sm_cma_ioctl_alloc alloc;
> -               memset(&alloc, 0, sizeof(alloc));
> -               alloc.size = size;
> -               alloc.num = 1;
> -               alloc.cached = cache;
> -               alloc.handle = 0;
> -               memcpy(alloc.name, name, 32);
> -
> -               ret = ::ioctl(vcsmHandle_, VC_SM_CMA_IOCTL_MEM_ALLOC, &alloc);
> -
> -               if (ret < 0 || alloc.handle < 0) {
> -                       std::cerr << "vcsm allocation failure for "
> -                                 << name << std::endl;
> -                       return nullptr;
> -               }
> -
> -               /* Map the buffer into user space. */
> -               user_ptr = ::mmap(0, alloc.size, PROT_READ | PROT_WRITE,
> -                                 MAP_SHARED, alloc.handle, 0);
> -
> -               if (user_ptr == MAP_FAILED) {
> -                       std::cerr << "vcsm mmap failure for " << name << std::endl;
> -                       ::close(alloc.handle);
> -                       return nullptr;
> -               }
> -
> -               std::lock_guard<std::mutex> lock(lock_);
> -               allocMap_.emplace(user_ptr, AllocInfo(alloc.handle,
> -                                                     alloc.size, alloc.vc_handle));
> -
> -               return user_ptr;
> -       }
> -
> -       void free(void *user_ptr)
> -       {
> -               std::lock_guard<std::mutex> lock(lock_);
> -               remove(user_ptr);
> -       }
> -
> -       unsigned int getVCHandle(void *user_ptr)
> -       {
> -               std::lock_guard<std::mutex> lock(lock_);
> -               auto it = allocMap_.find(user_ptr);
> -               if (it != allocMap_.end())
> -                       return it->second.vcHandle;
> -
> -               return 0;
> -       }
> -
> -private:
> -       struct AllocInfo {
> -               AllocInfo(int handle_, int size_, int vcHandle_)
> -                       : handle(handle_), size(size_), vcHandle(vcHandle_)
> -               {
> -               }
> -
> -               int handle;
> -               int size;
> -               uint32_t vcHandle;
> -       };
> -
> -       /* Map of all allocations that have been requested. */
> -       using AllocMap = std::map<void *, AllocInfo>;
> -
> -       AllocMap::iterator remove(void *user_ptr)
> -       {
> -               auto it = allocMap_.find(user_ptr);
> -               if (it != allocMap_.end()) {
> -                       int handle = it->second.handle;
> -                       int size = it->second.size;
> -                       ::munmap(user_ptr, size);
> -                       ::close(handle);
> -                       /*
> -                        * Remove the allocation from the map. This returns
> -                        * an iterator to the next element.
> -                        */
> -                       it = allocMap_.erase(it);
> -               }
> -
> -               /* Returns an iterator to the next element. */
> -               return it;
> -       }
> -
> -       AllocMap allocMap_;
> -       int vcsmHandle_;
> -       std::mutex lock_;
> -};
> -
> -} /* namespace RPi */
> -
> -#endif /* __LIBCAMERA_PIPELINE_RASPBERRYPI_VCSM_H__ */
> --
> Regards,
>
> Laurent Pinchart
>


More information about the libcamera-devel mailing list