forked from Minki/linux
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: Inki Dae <inki.dae@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
This commit is contained in:
parent
662aa6d763
commit
4744ad2414
@ -35,6 +35,7 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
|
enum dma_attr attr = DMA_ATTR_FORCE_CONTIGUOUS;
|
||||||
|
unsigned int nr_pages;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("%s\n", __FILE__);
|
DRM_DEBUG_KMS("%s\n", __FILE__);
|
||||||
|
|
||||||
@ -49,40 +50,31 @@ static int lowlevel_buffer_allocate(struct drm_device *dev,
|
|||||||
attr = DMA_ATTR_WRITE_COMBINE;
|
attr = DMA_ATTR_WRITE_COMBINE;
|
||||||
|
|
||||||
dma_set_attr(attr, &buf->dma_attrs);
|
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);
|
&buf->dma_addr, GFP_KERNEL, &buf->dma_attrs);
|
||||||
if (!buf->kvaddr) {
|
if (!buf->pages) {
|
||||||
DRM_ERROR("failed to allocate buffer.\n");
|
DRM_ERROR("failed to allocate buffer.\n");
|
||||||
return -ENOMEM;
|
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) {
|
if (!buf->sgt) {
|
||||||
DRM_ERROR("failed to allocate sg table.\n");
|
DRM_ERROR("failed to get sg table.\n");
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_free_attrs;
|
goto err_free_attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dma_get_sgtable(dev->dev, buf->sgt, buf->kvaddr, buf->dma_addr,
|
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
||||||
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,
|
|
||||||
(unsigned long)buf->dma_addr,
|
(unsigned long)buf->dma_addr,
|
||||||
buf->size);
|
buf->size);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err_free_sgt:
|
|
||||||
kfree(buf->sgt);
|
|
||||||
buf->sgt = NULL;
|
|
||||||
err_free_attrs:
|
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);
|
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
|
||||||
buf->dma_addr = (dma_addr_t)NULL;
|
buf->dma_addr = (dma_addr_t)NULL;
|
||||||
|
|
||||||
@ -99,8 +91,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
|
DRM_DEBUG_KMS("dma_addr(0x%lx), size(0x%lx)\n",
|
||||||
(unsigned long)buf->kvaddr,
|
|
||||||
(unsigned long)buf->dma_addr,
|
(unsigned long)buf->dma_addr,
|
||||||
buf->size);
|
buf->size);
|
||||||
|
|
||||||
@ -109,7 +100,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev,
|
|||||||
kfree(buf->sgt);
|
kfree(buf->sgt);
|
||||||
buf->sgt = NULL;
|
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);
|
(dma_addr_t)buf->dma_addr, &buf->dma_attrs);
|
||||||
buf->dma_addr = (dma_addr_t)NULL;
|
buf->dma_addr = (dma_addr_t)NULL;
|
||||||
}
|
}
|
||||||
|
@ -297,9 +297,7 @@ struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb,
|
|||||||
if (!buffer)
|
if (!buffer)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
|
DRM_DEBUG_KMS("dma_addr = 0x%lx\n", (unsigned long)buffer->dma_addr);
|
||||||
(unsigned long)buffer->kvaddr,
|
|
||||||
(unsigned long)buffer->dma_addr);
|
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ static int exynos_drm_fb_mmap(struct fb_info *info,
|
|||||||
if (vm_size > buffer->size)
|
if (vm_size > buffer->size)
|
||||||
return -EINVAL;
|
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);
|
buffer->dma_addr, buffer->size, &buffer->dma_attrs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
DRM_ERROR("failed to mmap.\n");
|
DRM_ERROR("failed to mmap.\n");
|
||||||
@ -109,6 +109,17 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
|
|||||||
return -EFAULT;
|
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. */
|
/* buffer count to framebuffer always is 1 at booting time. */
|
||||||
exynos_drm_fb_set_buf_cnt(fb, 1);
|
exynos_drm_fb_set_buf_cnt(fb, 1);
|
||||||
|
|
||||||
@ -305,8 +316,13 @@ err_init:
|
|||||||
static void exynos_drm_fbdev_destroy(struct drm_device *dev,
|
static void exynos_drm_fbdev_destroy(struct drm_device *dev,
|
||||||
struct drm_fb_helper *fb_helper)
|
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;
|
struct drm_framebuffer *fb;
|
||||||
|
|
||||||
|
if (exynos_gem_obj->buffer->kvaddr)
|
||||||
|
vunmap(exynos_gem_obj->buffer->kvaddr);
|
||||||
|
|
||||||
/* release drm framebuffer and real buffer */
|
/* release drm framebuffer and real buffer */
|
||||||
if (fb_helper->fb && fb_helper->fb->funcs) {
|
if (fb_helper->fb && fb_helper->fb->funcs) {
|
||||||
fb = fb_helper->fb;
|
fb = fb_helper->fb;
|
||||||
|
@ -400,7 +400,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
|
|||||||
if (vm_size > buffer->size)
|
if (vm_size > buffer->size)
|
||||||
return -EINVAL;
|
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_addr, buffer->size,
|
||||||
&buffer->dma_attrs);
|
&buffer->dma_attrs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
* - this address could be physical address without IOMMU and
|
* - this address could be physical address without IOMMU and
|
||||||
* device address with IOMMU.
|
* device address with IOMMU.
|
||||||
* @write: whether pages will be written to by the caller.
|
* @write: whether pages will be written to by the caller.
|
||||||
|
* @pages: Array of backing pages.
|
||||||
* @sgt: sg table to transfer page data.
|
* @sgt: sg table to transfer page data.
|
||||||
* @size: size of allocated memory region.
|
* @size: size of allocated memory region.
|
||||||
* @pfnmap: indicate whether memory region from userptr is mmaped with
|
* @pfnmap: indicate whether memory region from userptr is mmaped with
|
||||||
@ -51,6 +52,7 @@ struct exynos_drm_gem_buf {
|
|||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
struct dma_attrs dma_attrs;
|
struct dma_attrs dma_attrs;
|
||||||
unsigned int write;
|
unsigned int write;
|
||||||
|
struct page **pages;
|
||||||
struct sg_table *sgt;
|
struct sg_table *sgt;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
bool pfnmap;
|
bool pfnmap;
|
||||||
|
Loading…
Reference in New Issue
Block a user