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:
Jeremy Gebben
2013-03-12 14:03:54 -06:00
parent 57980d79f4
commit b55462afc7
9 changed files with 42 additions and 52 deletions
+4 -8
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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;
+1 -2
View File
@@ -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);
+4 -9
View File
@@ -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;
}
+5 -6
View File
@@ -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;
+2 -3
View File
@@ -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);
+17 -8
View File
@@ -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;
+4 -6
View File
@@ -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);
}