forked from rubenslte/android_kernel_samsung_msm8226
msm: kgsl: clean up iommu/gpummu protflag handling
Make kgsl_memdesc_protflags() return the correct type of flags for the type of mmu being used. Query the memdesc with this function in kgsl_mmu_map(), rather than passing in the protflags. This prevents translation at multiple layers of the code and makes it easier to enforce that the mapping matches the allocation flags. Change-Id: I2a2f4a43026ae903dd134be00e646d258a83f79f Signed-off-by: Jeremy Gebben <jgebben@codeaurora.org>
This commit is contained in:
@@ -251,23 +251,19 @@ static int adreno_setup_pt(struct kgsl_device *device,
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc,
|
||||
GSL_PT_PAGE_RV);
|
||||
result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
|
||||
if (result)
|
||||
goto error;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
|
||||
if (result)
|
||||
goto unmap_buffer_desc;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &device->memstore,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map_global(pagetable, &device->memstore);
|
||||
if (result)
|
||||
goto unmap_memptrs_desc;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
|
||||
if (result)
|
||||
goto unmap_memstore_desc;
|
||||
|
||||
|
||||
@@ -485,6 +485,7 @@ int adreno_ringbuffer_init(struct kgsl_device *device)
|
||||
*/
|
||||
rb->sizedwords = KGSL_RB_SIZE >> 2;
|
||||
|
||||
rb->buffer_desc.flags = KGSL_MEMFLAGS_GPUREADONLY;
|
||||
/* allocate memory for ringbuffer */
|
||||
status = kgsl_allocate_contiguous(&rb->buffer_desc,
|
||||
(rb->sizedwords << 2));
|
||||
|
||||
+4
-10
@@ -1875,10 +1875,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
||||
else if (entry->memdesc.size >= SZ_64K)
|
||||
kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
|
||||
|
||||
result = kgsl_mmu_map(private->pagetable,
|
||||
&entry->memdesc,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
|
||||
result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
|
||||
if (result)
|
||||
goto error_put_file_ptr;
|
||||
|
||||
@@ -2069,8 +2066,7 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv,
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
|
||||
kgsl_memdesc_protflags(&entry->memdesc));
|
||||
result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
|
||||
if (result)
|
||||
goto err;
|
||||
|
||||
@@ -2108,8 +2104,7 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv,
|
||||
goto err;
|
||||
|
||||
if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
|
||||
result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
|
||||
kgsl_memdesc_protflags(&entry->memdesc));
|
||||
result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
|
||||
if (result)
|
||||
goto err;
|
||||
}
|
||||
@@ -2723,8 +2718,7 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
|
||||
entry->memdesc.gpuaddr = vma->vm_start;
|
||||
|
||||
ret = kgsl_mmu_map(private->pagetable, &entry->memdesc,
|
||||
kgsl_memdesc_protflags(&entry->memdesc));
|
||||
ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
|
||||
if (ret) {
|
||||
kgsl_mem_entry_put(entry);
|
||||
return ret;
|
||||
|
||||
@@ -210,8 +210,7 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj)
|
||||
return result;
|
||||
}
|
||||
|
||||
result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
|
||||
if (result) {
|
||||
DRM_ERROR(
|
||||
"kgsl_mmu_map failed. result = %d\n", result);
|
||||
|
||||
@@ -1118,16 +1118,14 @@ static int kgsl_iommu_setup_regs(struct kgsl_mmu *mmu,
|
||||
|
||||
for (i = 0; i < iommu->unit_count; i++) {
|
||||
status = kgsl_mmu_map_global(pt,
|
||||
&(iommu->iommu_units[i].reg_map),
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
&(iommu->iommu_units[i].reg_map));
|
||||
if (status)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Map Lock variables to GPU pagetable */
|
||||
if (iommu->sync_lock_initialized) {
|
||||
status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc);
|
||||
if (status)
|
||||
goto err;
|
||||
}
|
||||
@@ -1499,22 +1497,19 @@ kgsl_iommu_map(void *mmu_specific_pt,
|
||||
unsigned int iommu_virt_addr;
|
||||
struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
|
||||
int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
|
||||
unsigned int iommu_flags = IOMMU_READ;
|
||||
|
||||
BUG_ON(NULL == iommu_pt);
|
||||
|
||||
if (protflags & GSL_PT_PAGE_WV)
|
||||
iommu_flags |= IOMMU_WRITE;
|
||||
|
||||
iommu_virt_addr = memdesc->gpuaddr;
|
||||
|
||||
ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg,
|
||||
size, iommu_flags);
|
||||
size, protflags);
|
||||
if (ret) {
|
||||
KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
|
||||
"failed with err: %d\n", iommu_pt->domain,
|
||||
iommu_virt_addr, memdesc->sg, size,
|
||||
iommu_flags, ret);
|
||||
protflags, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -580,13 +580,13 @@ void kgsl_mh_start(struct kgsl_device *device)
|
||||
|
||||
int
|
||||
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int protflags)
|
||||
struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int ret;
|
||||
struct gen_pool *pool = NULL;
|
||||
int size;
|
||||
int page_align = ilog2(PAGE_SIZE);
|
||||
unsigned int protflags = kgsl_memdesc_protflags(memdesc);
|
||||
|
||||
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
|
||||
if (memdesc->sglen == 1) {
|
||||
@@ -738,7 +738,7 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
|
||||
EXPORT_SYMBOL(kgsl_mmu_unmap);
|
||||
|
||||
int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
|
||||
struct kgsl_memdesc *memdesc, unsigned int protflags)
|
||||
struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
int result = -EINVAL;
|
||||
unsigned int gpuaddr = 0;
|
||||
@@ -750,11 +750,10 @@ int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
|
||||
/* Not all global mappings are needed for all MMU types */
|
||||
if (!memdesc->size)
|
||||
return 0;
|
||||
|
||||
gpuaddr = memdesc->gpuaddr;
|
||||
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
|
||||
|
||||
result = kgsl_mmu_map(pagetable, memdesc, protflags);
|
||||
result = kgsl_mmu_map(pagetable, memdesc);
|
||||
if (result)
|
||||
goto error;
|
||||
|
||||
|
||||
@@ -201,10 +201,9 @@ int kgsl_mmu_init(struct kgsl_device *device);
|
||||
int kgsl_mmu_start(struct kgsl_device *device);
|
||||
int kgsl_mmu_close(struct kgsl_device *device);
|
||||
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
|
||||
struct kgsl_memdesc *memdesc,
|
||||
unsigned int protflags);
|
||||
struct kgsl_memdesc *memdesc);
|
||||
int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
|
||||
struct kgsl_memdesc *memdesc, unsigned int protflags);
|
||||
struct kgsl_memdesc *memdesc);
|
||||
int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
|
||||
struct kgsl_memdesc *memdesc);
|
||||
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "kgsl_mmu.h"
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kmemleak.h>
|
||||
#include <linux/iommu.h>
|
||||
|
||||
#include "kgsl_log.h"
|
||||
|
||||
@@ -195,15 +196,24 @@ kgsl_memdesc_has_guard_page(const struct kgsl_memdesc *memdesc)
|
||||
/*
|
||||
* kgsl_memdesc_protflags - get mmu protection flags
|
||||
* @memdesc - the memdesc
|
||||
* Returns a mask of GSL_PT_PAGE* values based on the
|
||||
* memdesc flags.
|
||||
* Returns a mask of GSL_PT_PAGE* or IOMMU* values based
|
||||
* on the memdesc flags.
|
||||
*/
|
||||
static inline unsigned int
|
||||
kgsl_memdesc_protflags(const struct kgsl_memdesc *memdesc)
|
||||
{
|
||||
unsigned int protflags = GSL_PT_PAGE_RV;
|
||||
if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
|
||||
protflags |= GSL_PT_PAGE_WV;
|
||||
unsigned int protflags = 0;
|
||||
enum kgsl_mmutype mmutype = kgsl_mmu_get_mmutype();
|
||||
|
||||
if (mmutype == KGSL_MMU_TYPE_GPU) {
|
||||
protflags = GSL_PT_PAGE_RV;
|
||||
if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
|
||||
protflags |= GSL_PT_PAGE_WV;
|
||||
} else if (mmutype == KGSL_MMU_TYPE_IOMMU) {
|
||||
protflags = IOMMU_READ;
|
||||
if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
|
||||
protflags |= IOMMU_WRITE;
|
||||
}
|
||||
return protflags;
|
||||
}
|
||||
|
||||
@@ -248,8 +258,7 @@ kgsl_allocate(struct kgsl_memdesc *memdesc,
|
||||
ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = kgsl_mmu_map(pagetable, memdesc,
|
||||
kgsl_memdesc_protflags(memdesc));
|
||||
ret = kgsl_mmu_map(pagetable, memdesc);
|
||||
if (ret)
|
||||
kgsl_sharedmem_free(memdesc);
|
||||
return ret;
|
||||
|
||||
@@ -244,20 +244,17 @@ static int z180_setup_pt(struct kgsl_device *device,
|
||||
int result = 0;
|
||||
struct z180_device *z180_dev = Z180_DEVICE(device);
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
|
||||
|
||||
if (result)
|
||||
goto error;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable, &device->memstore,
|
||||
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
|
||||
result = kgsl_mmu_map_global(pagetable, &device->memstore);
|
||||
if (result)
|
||||
goto error_unmap_dummy;
|
||||
|
||||
result = kgsl_mmu_map_global(pagetable,
|
||||
&z180_dev->ringbuffer.cmdbufdesc,
|
||||
GSL_PT_PAGE_RV);
|
||||
&z180_dev->ringbuffer.cmdbufdesc);
|
||||
if (result)
|
||||
goto error_unmap_memstore;
|
||||
/*
|
||||
@@ -498,6 +495,7 @@ static int z180_ringbuffer_init(struct kgsl_device *device)
|
||||
struct z180_device *z180_dev = Z180_DEVICE(device);
|
||||
memset(&z180_dev->ringbuffer, 0, sizeof(struct z180_ringbuffer));
|
||||
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
|
||||
z180_dev->ringbuffer.cmdbufdesc.flags = KGSL_MEMFLAGS_GPUREADONLY;
|
||||
return kgsl_allocate_contiguous(&z180_dev->ringbuffer.cmdbufdesc,
|
||||
Z180_RB_SIZE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user