From d08f8cd31cb06aea5d7f5b4238996876911e6c08 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Thu, 8 Oct 2020 17:20:18 +0530 Subject: [PATCH] msm: kgsl: make per process stats atomic There is a chance of messing up per process stats if something like a free and allocation happen at the same time for memory belonging to the same process. So make per process stats atomic. Decrement process stats when mem entry is destroyed. Also make sure that mapsize is updated for all the memdescs. Change-Id: I5da1cf368d523768d0b267b314394612934a620d Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/kgsl.c | 25 ++++++++++++------------- drivers/gpu/msm/kgsl_device.h | 4 ++-- drivers/gpu/msm/kgsl_sharedmem.c | 14 +++++++++----- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 3a466a20d8a6..03302654e960 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -343,6 +343,8 @@ kgsl_mem_entry_destroy(struct kref *kref) /* pull out the memtype before the flags get cleared */ memtype = kgsl_memdesc_usermem_type(&entry->memdesc); + atomic64_sub(entry->memdesc.size, &entry->priv->stats[memtype].cur); + /* Detach from process list */ kgsl_mem_entry_detach_process(entry); @@ -491,8 +493,6 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) idr_remove(&entry->priv->mem_idr, entry->id); entry->id = 0; - entry->priv->gpumem_mapped -= entry->memdesc.mapsize; - spin_unlock(&entry->priv->mem_lock); kgsl_mmu_put_gpuaddr(&entry->memdesc); @@ -2676,9 +2676,10 @@ static long _gpuobj_map_dma_buf(struct kgsl_device *device, static void kgsl_process_add_stats(struct kgsl_process_private *priv, unsigned int type, uint64_t size) { - priv->stats[type].cur += size; - if (priv->stats[type].max < priv->stats[type].cur) - priv->stats[type].max = priv->stats[type].cur; + u64 ret = atomic64_add_return(size, &priv->stats[type].cur); + + if (ret > priv->stats[type].max) + priv->stats[type].max = ret; } @@ -3710,18 +3711,13 @@ static vm_fault_t kgsl_gpumem_vm_fault(struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vmf->vma->vm_private_data; - vm_fault_t ret; if (!entry) return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; - ret = entry->memdesc.ops->vmfault(&entry->memdesc, vmf->vma, vmf); - if (!ret || ret == VM_FAULT_NOPAGE) - entry->priv->gpumem_mapped += PAGE_SIZE; - - return ret; + return entry->memdesc.ops->vmfault(&entry->memdesc, vmf->vma, vmf); } static void @@ -3733,6 +3729,8 @@ kgsl_gpumem_vm_close(struct vm_area_struct *vma) return; entry->memdesc.useraddr = 0; + atomic64_sub(entry->memdesc.mapsize, &entry->priv->gpumem_mapped); + entry->memdesc.mapsize = 0; kgsl_mem_entry_put(entry); } @@ -4017,14 +4015,15 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma) vm_insert_page(vma, addr, page); addr += PAGE_SIZE; } - m->mapsize = m->size; - entry->priv->gpumem_mapped += m->mapsize; } vma->vm_file = file; entry->memdesc.useraddr = vma->vm_start; + entry->memdesc.mapsize += entry->memdesc.size; + atomic64_add(entry->memdesc.mapsize, &entry->priv->gpumem_mapped); + trace_kgsl_mem_mmap(entry); return 0; } diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 6140fc2b8055..c639b5112977 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -437,10 +437,10 @@ struct kgsl_process_private { struct kobject kobj; struct dentry *debug_root; struct { - uint64_t cur; + atomic64_t cur; uint64_t max; } stats[KGSL_MEM_ENTRY_MAX]; - uint64_t gpumem_mapped; + atomic64_t gpumem_mapped; struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index c4d3ee7e6967..0ddc99248f54 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -113,18 +113,21 @@ static ssize_t gpumem_mapped_show(struct kgsl_process_private *priv, int type, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%llu\n", - priv->gpumem_mapped); + return scnprintf(buf, PAGE_SIZE, "%lld\n", + atomic64_read(&priv->gpumem_mapped)); } static ssize_t gpumem_unmapped_show(struct kgsl_process_private *priv, int type, char *buf) { - if (priv->gpumem_mapped > priv->stats[type].cur) + u64 gpumem_total = atomic64_read(&priv->stats[type].cur); + u64 gpumem_mapped = atomic64_read(&priv->gpumem_mapped); + + if (gpumem_mapped > gpumem_total) return -EIO; return scnprintf(buf, PAGE_SIZE, "%llu\n", - priv->stats[type].cur - priv->gpumem_mapped); + gpumem_total - gpumem_mapped); } static struct kgsl_mem_entry_attribute debug_memstats[] = { @@ -141,7 +144,8 @@ static struct kgsl_mem_entry_attribute debug_memstats[] = { static ssize_t mem_entry_show(struct kgsl_process_private *priv, int type, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%llu\n", priv->stats[type].cur); + return scnprintf(buf, PAGE_SIZE, "%lld\n", + atomic64_read(&priv->stats[type].cur)); } /**