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

Commit 4744ad24 authored by Inki Dae's avatar Inki Dae Committed by Inki Dae
Browse files

drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute



Changelog v3:
just code cleanup.

Changelog v2:
fix argument to dma_mmap_attr function.
- use pages instead of kvaddr because kvaddr is 0 with
  DMA_ATTR_NO_KERNEL_MAPPING.

Changelog v1:
When gem allocation is requested, kernel space mapping isn't needed.
But if need, such as console framebuffer, the physical pages would be
mapped with kernel space though vmap function.

Signed-off-by: default avatarInki Dae <inki.dae@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
parent 662aa6d7
Loading
Loading
Loading
Loading
+11 −20
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
{
	int ret = 0;
	enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
	unsigned int nr_pages;

	DRM_DEBUG_KMS("%s\n", __FILE__);

@@ -49,40 +50,31 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
		attr = DMA_ATTR_WRITE_COMBINE;

	dma_set_attr(attr, &buf->dma_attrs);
	dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &buf->dma_attrs);

	buf->kvaddr = dma_alloc_attrs(dev->dev, buf->size,
	buf->pages = dma_alloc_attrs(dev->dev, buf->size,
			&buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
	if (!buf->kvaddr) {
	if (!buf->pages) {
		DRM_ERROR("failed to allocate buffer.\n");
		return -ENOMEM;
	}

	buf->sgt = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
	nr_pages = buf->size >> PAGE_SHIFT;
	buf->sgt = drm_prime_pages_to_sg(buf->pages, nr_pages);
	if (!buf->sgt) {
		DRM_ERROR("failed to allocate sg table.\n");
		DRM_ERROR("failed to get sg table.\n");
		ret = -ENOMEM;
		goto err_free_attrs;
	}

	ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr,
			buf->size);
	if (ret < 0) {
		DRM_ERROR("failed to get sgtable.\n");
		goto err_free_sgt;
	}

	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
			(unsigned long)buf->kvaddr,
	DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
			(unsigned long)buf->dma_addr,
			buf->size);

	return ret;

err_free_sgt:
	kfree(buf->sgt);
	buf->sgt = NULL;
err_free_attrs:
	dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
	dma_free_attrs(dev->dev, buf->size, buf->pages,
			(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
	buf->dma_addr = (dma_addr_t)NULL;

@@ -99,8 +91,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
		return;
	}

	DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
			(unsigned long)buf->kvaddr,
	DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
			(unsigned long)buf->dma_addr,
			buf->size);

@@ -109,7 +100,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
	kfree(buf->sgt);
	buf->sgt = NULL;

	dma_free_attrs(dev->dev, buf->size, buf->kvaddr,
	dma_free_attrs(dev->dev, buf->size, buf->pages,
				(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
	buf->dma_addr = (dma_addr_t)NULL;
}
+1 −3
Original line number Diff line number Diff line
@@ -297,9 +297,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
	if (!buffer)
		return NULL;

	DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
			(unsigned long)buffer->kvaddr,
			(unsigned long)buffer->dma_addr);
	DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);

	return buffer;
}
+17 −1
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
	if (vm_size > buffer->size)
		return -EINVAL;

	ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->kvaddr,
	ret = dma_mmap_attrs(helper->dev->dev, vma, buffer->pages,
		buffer->dma_addr, buffer->size, &buffer->dma_attrs);
	if (ret < 0) {
		DRM_ERROR("failed to mmap.\n");
@@ -109,6 +109,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
		return -EFAULT;
	}

	/* map pages with kernel virtual space. */
	if (!buffer->kvaddr) {
		unsigned int nr_pages = buffer->size >> PAGE_SHIFT;
		buffer->kvaddr = vmap(buffer->pages, nr_pages, VM_MAP,
					pgprot_writecombine(PAGE_KERNEL));
		if (!buffer->kvaddr) {
			DRM_ERROR("failed to map pages to kernel space.\n");
			return -EIO;
		}
	}

	/* buffer count to framebuffer always is 1 at booting time. */
	exynos_drm_fb_set_buf_cnt(fb, 1);

@@ -305,8 +316,13 @@ int exynos_drm_fbdev_init(struct drm_device *dev)
static void exynos_drm_fbdev_destroy(struct drm_device *dev,
				      struct drm_fb_helper *fb_helper)
{
	struct exynos_drm_fbdev *exynos_fbd = to_exynos_fbdev(fb_helper);
	struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj;
	struct drm_framebuffer *fb;

	if (exynos_gem_obj->buffer->kvaddr)
		vunmap(exynos_gem_obj->buffer->kvaddr);

	/* release drm framebuffer and real buffer */
	if (fb_helper->fb && fb_helper->fb->funcs) {
		fb = fb_helper->fb;
+1 −1
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
	if (vm_size > buffer->size)
		return -EINVAL;

	ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->kvaddr,
	ret = dma_mmap_attrs(drm_dev->dev, vma, buffer->pages,
				buffer->dma_addr, buffer->size,
				&buffer->dma_attrs);
	if (ret < 0) {
+2 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
 *	- this address could be physical address without IOMMU and
 *	device address with IOMMU.
 * @write: whether pages will be written to by the caller.
 * @pages: Array of backing pages.
 * @sgt: sg table to transfer page data.
 * @size: size of allocated memory region.
 * @pfnmap: indicate whether memory region from userptr is mmaped with
@@ -51,6 +52,7 @@ struct exynos_drm_gem_buf {
	dma_addr_t		dma_addr;
	struct dma_attrs	dma_attrs;
	unsigned int		write;
	struct page		**pages;
	struct sg_table		*sgt;
	unsigned long		size;
	bool			pfnmap;