Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01a6fad1 authored by Gjorgji Rosikopulos's avatar Gjorgji Rosikopulos
Browse files

msm: camera: fd: Attach iommu dynamically



When iommu device is attached, iommu
framework will keep the regulator enabled.

We should not attach iommu if buffers are not
used. Move attach iommu from open to map
buffers, and detach iommu from release to
unmap buffers.

Change-Id: Ifdf56bd43f1e1f3b9077c6879063bc61b5b7d929
Signed-off-by: default avatarGjorgji Rosikopulos <grosik@codeaurora.org>
parent e92aa60f
Loading
Loading
Loading
Loading
+1 −13
Original line number Diff line number Diff line
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/iommu.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/ion.h>
@@ -375,15 +374,9 @@ static int msm_fd_open(struct file *file)
		dev_err(device->dev, "Error ion client create\n");
		goto error_ion_client_create;
	}
	ctx->mem_pool.fd_device = ctx->fd_device;
	ctx->mem_pool.domain_num = ctx->fd_device->iommu_domain_num;

	ret = iommu_attach_device(ctx->fd_device->iommu_domain,
		ctx->fd_device->iommu_dev);
	if (ret) {
		dev_err(device->dev, "Can not attach iommu domain\n");
		goto error_iommu_attach;
	}

	ctx->stats = vmalloc(sizeof(*ctx->stats) * MSM_FD_MAX_RESULT_BUFS);
	if (!ctx->stats) {
		dev_err(device->dev, "No memory for face statistics\n");
@@ -394,9 +387,6 @@ static int msm_fd_open(struct file *file)
	return 0;

error_stats_vmalloc:
	iommu_detach_device(ctx->fd_device->iommu_domain,
			ctx->fd_device->iommu_dev);
error_iommu_attach:
	ion_client_destroy(ctx->mem_pool.client);
error_ion_client_create:
	vb2_queue_release(&ctx->vb2_q);
@@ -422,8 +412,6 @@ static int msm_fd_release(struct file *file)
	if (ctx->work_buf.handle)
		msm_fd_hw_unmap_buffer(&ctx->work_buf);

	iommu_detach_device(ctx->fd_device->iommu_domain,
		ctx->fd_device->iommu_dev);
	ion_client_destroy(ctx->mem_pool.client);

	v4l2_fh_del(&ctx->fh);
+4 −0
Original line number Diff line number Diff line
@@ -75,10 +75,12 @@ struct msm_fd_format {

/*
 * struct msm_fd_mem_pool - Structure contain FD memory pool information.
 * @fd_device: Pointer to fd device.
 * @client: Pointer to ion client.
 * @domain_num: Domain number associated with FD hw.
 */
struct msm_fd_mem_pool {
	struct msm_fd_device *fd_device;
	struct ion_client *client;
	int domain_num;
};
@@ -197,6 +199,7 @@ enum msm_fd_mem_resources {
 * @bus_client: Memory access bus client.
 * @iommu_domain: Pointer to FD device iommu domain handler.
 * @iommu_domain_num: FD device iommu domain number.
 * @iommu_attached_cnt: Iommu attached devices reference count.
 * @iommu_dev: Pointer to Ion iommu device.
 * @dev: Pointer to device struct.
 * @v4l2_dev: V4l2 device.
@@ -226,6 +229,7 @@ struct msm_fd_device {

	struct iommu_domain *iommu_domain;
	int iommu_domain_num;
	unsigned int iommu_attached_cnt;

	struct device *iommu_dev;
	struct device *dev;
+68 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/regulator/consumer.h>
#include <linux/msm_iommu_domains.h>
#include <linux/spinlock.h>
#include <linux/iommu.h>
#include <linux/qcom_iommu.h>
#include <linux/msm_ion.h>
#include <linux/msm-bus.h>
@@ -814,6 +815,63 @@ void msm_fd_hw_put(struct msm_fd_device *fd)
	mutex_unlock(&fd->lock);
}

/*
 * msm_fd_hw_attach_iommu - Attach iommu to face detection engine.
 * @fd: Pointer to fd device.
 *
 * Iommu attach have reference count protected by
 * fd device mutex.
 */
static int msm_fd_hw_attach_iommu(struct msm_fd_device *fd)
{
	int ret;

	mutex_lock(&fd->lock);

	if (fd->iommu_attached_cnt == UINT_MAX) {
		dev_err(fd->dev, "Max count reached! can not attach iommu\n");
		goto error;
	}

	if (fd->iommu_attached_cnt == 0) {
		ret = iommu_attach_device(fd->iommu_domain, fd->iommu_dev);
		if (ret < 0) {
			dev_err(fd->dev, "Can not attach iommu domain\n");
			goto error;
		}
	}
	fd->iommu_attached_cnt++;
	mutex_unlock(&fd->lock);

	return 0;

error:
	mutex_unlock(&fd->lock);
	return ret;
}

/*
 * msm_fd_hw_detach_iommu - Detach iommu from face detection engine.
 * @fd: Pointer to fd device.
 *
 * Iommu detach have reference count protected by
 * fd device mutex.
 */
static void msm_fd_hw_detach_iommu(struct msm_fd_device *fd)
{
	mutex_lock(&fd->lock);
	if (fd->iommu_attached_cnt == 0) {
		dev_err(fd->dev, "There is no attached device\n");
		mutex_unlock(&fd->lock);
		return;
	}

	if (--fd->iommu_attached_cnt == 0)
		iommu_detach_device(fd->iommu_domain, fd->iommu_dev);

	mutex_unlock(&fd->lock);
}

/*
 * msm_fd_hw_map_buffer - Map buffer to fd hw mmu.
 * @pool: Pointer to fd memory pool.
@@ -830,12 +888,16 @@ int msm_fd_hw_map_buffer(struct msm_fd_mem_pool *pool, int fd,
	if (!pool || fd < 0)
		return -EINVAL;

	ret = msm_fd_hw_attach_iommu(pool->fd_device);
	if (ret < 0)
		goto error;

	buf->pool = pool;
	buf->fd = fd;

	buf->handle = ion_import_dma_buf(pool->client, buf->fd);
	if (IS_ERR_OR_NULL(buf->handle))
		goto error;
		goto error_import_dma;

	ret = ion_map_iommu(pool->client, buf->handle, pool->domain_num,
		0, SZ_4K, 0, &buf->addr, &buf->size, 0, 0);
@@ -846,6 +908,8 @@ int msm_fd_hw_map_buffer(struct msm_fd_mem_pool *pool, int fd,

error_map_iommu:
	ion_free(pool->client, buf->handle);
error_import_dma:
	msm_fd_hw_detach_iommu(pool->fd_device);
error:
	return -ENOMEM;
}
@@ -856,9 +920,11 @@ error:
 */
void msm_fd_hw_unmap_buffer(struct msm_fd_buf_handle *buf)
{
	if (buf->size)
	if (buf->size) {
		ion_unmap_iommu(buf->pool->client, buf->handle,
			buf->pool->domain_num, 0);
		msm_fd_hw_detach_iommu(buf->pool->fd_device);
	}

	if (!IS_ERR_OR_NULL(buf->handle))
		ion_free(buf->pool->client, buf->handle);