diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c index e4888c89d7c307be09ec794bdbad848e1c36ae3e..ef641c19886660f881f2f93ef8202ea0300f609a 100644 --- a/drivers/gpu/msm/adreno_a2xx.c +++ b/drivers/gpu/msm/adreno_a2xx.c @@ -1352,7 +1352,8 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size); tmp_ctx.gmem_base = adreno_dev->gmem_base; - result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, + result = kgsl_allocate(&(adreno_dev->dev), + &drawctxt->context_gmem_shadow.gmemshadow, drawctxt->base.proc_priv->pagetable, drawctxt->context_gmem_shadow.size); @@ -1450,7 +1451,7 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, * and texture and vertex buffer storage too */ - ret = kgsl_allocate(&drawctxt->gpustate, + ret = kgsl_allocate(&(adreno_dev->dev), &drawctxt->gpustate, drawctxt->base.proc_priv->pagetable, _context_size(adreno_dev)); if (ret) diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 26bdb4820ba767b601c94f04df27ae2384afc318..65d1d063cd21eabc701a03cacb020db14ffb550c 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -2318,7 +2318,8 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev, calc_gmemsize(&drawctxt->context_gmem_shadow, adreno_dev->gmem_size); tmp_ctx.gmem_base = adreno_dev->gmem_base; - result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, + result = kgsl_allocate(&(adreno_dev->dev), + &drawctxt->context_gmem_shadow.gmemshadow, drawctxt->base.proc_priv->pagetable, drawctxt->context_gmem_shadow.size); @@ -2374,7 +2375,7 @@ static int a3xx_drawctxt_create(struct adreno_device *adreno_dev, } drawctxt->ops = &a3xx_legacy_ctx_ops; - ret = kgsl_allocate(&drawctxt->gpustate, + ret = kgsl_allocate(&(adreno_dev->dev), &drawctxt->gpustate, drawctxt->base.proc_priv->pagetable, CONTEXT_SIZE); if (ret) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index af13a48c3f7b42898b8d5a31f57db5d695606308..1fb787c449d2b49e38cbdf87db0c44d2c64d51e0 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2809,7 +2809,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, | KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags = param->flags; - if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) + if (!kgsl_mmu_use_cpu_map(&dev_priv->device->mmu)) entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) @@ -3141,8 +3141,8 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv, if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) entry->memdesc.priv |= KGSL_MEMDESC_GUARD_PAGE; - result = kgsl_allocate_user(&entry->memdesc, private->pagetable, size, - flags); + result = kgsl_allocate_user(dev_priv->device, &entry->memdesc, + private->pagetable, size, flags); if (result != 0) goto err; @@ -3192,11 +3192,12 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *private = dev_priv->process_priv; + struct kgsl_device *device = dev_priv->device; struct kgsl_gpumem_alloc_id *param = data; struct kgsl_mem_entry *entry = NULL; int result; - if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) + if (!kgsl_mmu_use_cpu_map(&device->mmu)) param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 10122786979e8cefb2f174b55a199fc2d74ab9c3..7ab469efb97588a0ed21200c5e03ed021a7d27bb 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -178,6 +178,7 @@ struct kgsl_memdesc { unsigned int sglen_alloc; /* Allocated entries in the sglist */ struct kgsl_memdesc_ops *ops; unsigned int flags; /* Flags set from userspace */ + struct device *dev; }; /* List of different memory entry types */ diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index 5ddc46b3c57b61cf305c83b5bc1718c81fde851f..d987c3d1d6a0e38186e796036595a5a57a751553 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -20,6 +20,7 @@ #include <linux/iommu.h> #include <mach/iommu.h> #include <mach/socinfo.h> +#include <linux/types.h> #include "kgsl.h" #include "kgsl_mmu.h" @@ -395,6 +396,8 @@ int kgsl_mmu_init(struct kgsl_device *device) if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) { dev_info(device->dev, "|%s| MMU type set for device is " "NOMMU\n", __func__); + status = dma_set_coherent_mask(device->dev->parent, + DMA_BIT_MASK(sizeof(dma_addr_t)*8)); goto done; } else if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type) mmu->mmu_ops = &gpummu_ops; @@ -734,6 +737,10 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, if (!kgsl_memdesc_is_global(memdesc) && (KGSL_MEMDESC_MAPPED & memdesc->priv)) return -EINVAL; + + if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE) + return 0; + /* Add space for the guard page when allocating the mmu VA. */ size = memdesc->size; if (kgsl_memdesc_has_guard_page(memdesc)) diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 4f05780bc323fd0dea4db1afc11f8dd5dde349f3..7741c5a86a250b315c3a02b0daf989ea0d9de119 100755 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -518,58 +518,20 @@ static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, return VM_FAULT_NOPAGE; } -static void kgsl_ebimem_unmap_kernel(struct kgsl_memdesc *memdesc) -{ - mutex_lock(&kernel_map_global_lock); - if (!memdesc->hostptr) { - BUG_ON(memdesc->hostptr_count); - goto done; - } - memdesc->hostptr_count--; - if (memdesc->hostptr_count) - goto done; - - iounmap(memdesc->hostptr); - memdesc->hostptr = NULL; -done: - mutex_unlock(&kernel_map_global_lock); -} - -static void kgsl_ebimem_free(struct kgsl_memdesc *memdesc) - +static void kgsl_coherent_free(struct kgsl_memdesc *memdesc) { kgsl_driver.stats.coherent -= memdesc->size; - kgsl_ebimem_unmap_kernel(memdesc); - /* we certainly do not expect the hostptr to still be mapped */ - BUG_ON(memdesc->hostptr); - - free_contiguous_memory_by_paddr(memdesc->physaddr); + dma_free_coherent(NULL, memdesc->size, + memdesc->hostptr, memdesc->physaddr); } -static int kgsl_ebimem_map_kernel(struct kgsl_memdesc *memdesc) +static void kgsl_cma_coherent_free(struct kgsl_memdesc *memdesc) { - int ret = 0; - mutex_lock(&kernel_map_global_lock); - if (!memdesc->hostptr) { - memdesc->hostptr = ioremap(memdesc->physaddr, memdesc->size); - if (!memdesc->hostptr) { - KGSL_CORE_ERR("ioremap failed, addr:0x%p, size:0x%x\n", - memdesc->hostptr, memdesc->size); - ret = -ENOMEM; - goto done; - } + if (memdesc->hostptr) { + kgsl_driver.stats.coherent -= memdesc->size; + dma_free_coherent(memdesc->dev, memdesc->size, + memdesc->hostptr, memdesc->physaddr); } - memdesc->hostptr_count++; -done: - mutex_unlock(&kernel_map_global_lock); - return ret; -} - -static void kgsl_coherent_free(struct kgsl_memdesc *memdesc) -{ - kgsl_driver.stats.coherent -= memdesc->size; - dma_free_coherent(NULL, memdesc->size, - memdesc->hostptr, memdesc->physaddr); } /* Global - also used by kgsl_drm.c */ @@ -582,12 +544,11 @@ struct kgsl_memdesc_ops kgsl_page_alloc_ops = { }; EXPORT_SYMBOL(kgsl_page_alloc_ops); -static struct kgsl_memdesc_ops kgsl_ebimem_ops = { - .free = kgsl_ebimem_free, +/* CMA ops - used during NOMMU mode */ +static struct kgsl_memdesc_ops kgsl_cma_ops = { + .free = kgsl_cma_coherent_free, .vmflags = kgsl_contiguous_vmflags, .vmfault = kgsl_contiguous_vmfault, - .map_kernel = kgsl_ebimem_map_kernel, - .unmap_kernel = kgsl_ebimem_unmap_kernel, }; static struct kgsl_memdesc_ops kgsl_coherent_ops = { @@ -893,77 +854,6 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) } EXPORT_SYMBOL(kgsl_sharedmem_free); -static int -_kgsl_sharedmem_ebimem(struct kgsl_memdesc *memdesc, - struct kgsl_pagetable *pagetable, size_t size) -{ - int result = 0; - - memdesc->size = size; - memdesc->pagetable = pagetable; - memdesc->ops = &kgsl_ebimem_ops; - memdesc->physaddr = allocate_contiguous_ebi_nomap(size, SZ_8K); - - if (memdesc->physaddr == 0) { - KGSL_CORE_ERR("allocate_contiguous_ebi_nomap(%d) failed\n", - size); - return -ENOMEM; - } - - result = memdesc_sg_phys(memdesc, memdesc->physaddr, size); - - if (result) - goto err; - - KGSL_STATS_ADD(size, kgsl_driver.stats.coherent, - kgsl_driver.stats.coherent_max); - -err: - if (result) - kgsl_sharedmem_free(memdesc); - - return result; -} - -int -kgsl_sharedmem_ebimem_user(struct kgsl_memdesc *memdesc, - struct kgsl_pagetable *pagetable, - size_t size) -{ - size = ALIGN(size, PAGE_SIZE); - if (size == 0) - return -EINVAL; - - return _kgsl_sharedmem_ebimem(memdesc, pagetable, size); -} -EXPORT_SYMBOL(kgsl_sharedmem_ebimem_user); - -int -kgsl_sharedmem_ebimem(struct kgsl_memdesc *memdesc, - struct kgsl_pagetable *pagetable, size_t size) -{ - int result; - size = ALIGN(size, 8192); - if (size == 0) - return -EINVAL; - - result = _kgsl_sharedmem_ebimem(memdesc, pagetable, size); - - if (result) - return result; - - result = kgsl_ebimem_map_kernel(memdesc); - - if (result) { - KGSL_CORE_ERR("hostptr mapping failed\n"); - kgsl_sharedmem_free(memdesc); - return result; - } - - return 0; -} -EXPORT_SYMBOL(kgsl_sharedmem_ebimem); - int kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, uint32_t *dst, @@ -1092,3 +982,42 @@ void kgsl_get_memory_usage(char *name, size_t name_size, unsigned int memflags) snprintf(name, name_size, "unknown(%3d)", type); } EXPORT_SYMBOL(kgsl_get_memory_usage); + +int kgsl_cma_alloc_coherent(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, + struct kgsl_pagetable *pagetable, size_t size) +{ + int result = 0; + + if (size == 0) + return -EINVAL; + + memdesc->size = size; + memdesc->pagetable = pagetable; + memdesc->ops = &kgsl_cma_ops; + memdesc->dev = device->dev->parent; + + memdesc->hostptr = dma_alloc_coherent(memdesc->dev, size, + &memdesc->physaddr, GFP_KERNEL); + + if (memdesc->hostptr == NULL) { + result = -ENOMEM; + goto err; + } + + result = memdesc_sg_phys(memdesc, memdesc->physaddr, size); + if (result) + goto err; + + /* Record statistics */ + + KGSL_STATS_ADD(size, kgsl_driver.stats.coherent, + kgsl_driver.stats.coherent_max); + +err: + if (result) + kgsl_sharedmem_free(memdesc); + + return result; +} +EXPORT_SYMBOL(kgsl_cma_alloc_coherent); diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index f0114ad195fc29af104143999222a4c66e5f7525..8a2e7c490f7a7dd5019ba4aa02f35baf13e0f4fd 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -41,13 +41,9 @@ int kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, int kgsl_sharedmem_alloc_coherent(struct kgsl_memdesc *memdesc, size_t size); -int kgsl_sharedmem_ebimem_user(struct kgsl_memdesc *memdesc, - struct kgsl_pagetable *pagetable, - size_t size); - -int kgsl_sharedmem_ebimem(struct kgsl_memdesc *memdesc, - struct kgsl_pagetable *pagetable, - size_t size); +int kgsl_cma_alloc_coherent(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, + struct kgsl_pagetable *pagetable, size_t size); void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc); @@ -253,14 +249,16 @@ kgsl_memdesc_mmapsize(const struct kgsl_memdesc *memdesc) } static inline int -kgsl_allocate(struct kgsl_memdesc *memdesc, +kgsl_allocate(struct kgsl_device *device, struct kgsl_memdesc *memdesc, struct kgsl_pagetable *pagetable, size_t size) { int ret; memdesc->priv |= (KGSL_MEMTYPE_KERNEL << KGSL_MEMTYPE_SHIFT); - if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE) - return kgsl_sharedmem_ebimem(memdesc, pagetable, size); - + if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE) { + size = ALIGN(size, PAGE_SIZE * 2); + return kgsl_cma_alloc_coherent(device, memdesc, pagetable, + size); + } ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size); if (ret) return ret; @@ -276,7 +274,8 @@ kgsl_allocate(struct kgsl_memdesc *memdesc, } static inline int -kgsl_allocate_user(struct kgsl_memdesc *memdesc, +kgsl_allocate_user(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, struct kgsl_pagetable *pagetable, size_t size, unsigned int flags) { @@ -287,8 +286,10 @@ kgsl_allocate_user(struct kgsl_memdesc *memdesc, memdesc->flags = flags; - if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE) - ret = kgsl_sharedmem_ebimem_user(memdesc, pagetable, size); + if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_NONE) { + size = ALIGN(size, PAGE_SIZE); + ret = kgsl_cma_alloc_coherent(device, memdesc, pagetable, size); + } else ret = kgsl_sharedmem_page_alloc_user(memdesc, pagetable, size);