diff options
Diffstat (limited to 'drivers/gpu/msm/kgsl.c')
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 986026aa1b66..b2def8dea954 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -255,6 +255,13 @@ static void _deferred_put(struct work_struct *work) kgsl_mem_entry_put(entry); } +static inline void +kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry) +{ + if (entry) + queue_work(kgsl_driver.mem_workqueue, &entry->work); +} + static inline struct kgsl_mem_entry * kgsl_mem_entry_create(void) { @@ -265,6 +272,7 @@ kgsl_mem_entry_create(void) /* put this ref in the caller functions after init */ kref_get(&entry->refcount); + INIT_WORK(&entry->work, _deferred_put); } return entry; } @@ -1230,7 +1238,8 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr) spin_lock(&private->mem_lock); idr_for_each_entry(&private->mem_idr, entry, id) { if (GPUADDR_IN_MEMDESC(gpuaddr, &entry->memdesc)) { - ret = kgsl_mem_entry_get(entry); + if (!entry->pending_free) + ret = kgsl_mem_entry_get(entry); break; } } @@ -1860,7 +1869,7 @@ long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, return -EINVAL; ret = gpumem_free_entry(entry); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_put_deferred(entry); return ret; } @@ -1878,7 +1887,7 @@ long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv, return -EINVAL; ret = gpumem_free_entry(entry); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_put_deferred(entry); return ret; } @@ -1915,8 +1924,7 @@ static void gpuobj_free_fence_func(void *priv) { struct kgsl_mem_entry *entry = priv; - INIT_WORK(&entry->work, _deferred_put); - queue_work(kgsl_driver.mem_workqueue, &entry->work); + kgsl_mem_entry_put_deferred(entry); } static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv, @@ -1980,7 +1988,7 @@ long kgsl_ioctl_gpuobj_free(struct kgsl_device_private *dev_priv, else ret = -EINVAL; - kgsl_mem_entry_put(entry); + kgsl_mem_entry_put_deferred(entry); return ret; } @@ -3355,7 +3363,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv, if (entry == NULL) return -EINVAL; + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } + if (entry->memdesc.cur_bindings != 0) { + kgsl_mem_entry_unset_pend(entry); kgsl_mem_entry_put(entry); return -EINVAL; } @@ -3364,7 +3378,7 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv, /* One put for find_id(), one put for the kgsl_mem_entry_create() */ kgsl_mem_entry_put(entry); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_put_deferred(entry); return 0; } @@ -3424,7 +3438,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv, if (entry == NULL) return -EINVAL; + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } + if (entry->bind_tree.rb_node != NULL) { + kgsl_mem_entry_unset_pend(entry); kgsl_mem_entry_put(entry); return -EINVAL; } @@ -3433,7 +3453,7 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv, /* One put for find_id(), one put for the kgsl_mem_entry_create() */ kgsl_mem_entry_put(entry); - kgsl_mem_entry_put(entry); + kgsl_mem_entry_put_deferred(entry); return 0; } @@ -4906,7 +4926,7 @@ static int __init kgsl_core_init(void) WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); kgsl_driver.mem_workqueue = alloc_workqueue("kgsl-mementry", - WQ_UNBOUND | WQ_MEM_RECLAIM, 0); + WQ_MEM_RECLAIM, 0); kgsl_events_init(); |
