Loading drivers/gpu/msm/kgsl.c +39 −27 Original line number Diff line number Diff line Loading @@ -343,22 +343,29 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, */ static int kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, struct kgsl_process_private *process) struct kgsl_device_private *dev_priv) { int id; int ret; struct kgsl_process_private *process = dev_priv->process_priv; ret = kref_get_unless_zero(&process->refcount); if (!ret) return -EBADF; idr_preload(GFP_KERNEL); spin_lock(&process->mem_lock); id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); spin_unlock(&process->mem_lock); idr_preload_end(); if (id < 0) return id; if (id < 0) { ret = id; goto err_put_proc_priv; } entry->id = id; entry->priv = process; entry->dev_priv = dev_priv; spin_lock(&process->mem_lock); ret = kgsl_mem_entry_track_gpuaddr(process, entry); Loading @@ -366,14 +373,17 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, idr_remove(&process->mem_idr, entry->id); spin_unlock(&process->mem_lock); if (ret) goto err; goto err_put_proc_priv; /* map the memory after unlocking if gpuaddr has been assigned */ if (entry->memdesc.gpuaddr) { ret = kgsl_mmu_map(process->pagetable, &entry->memdesc); if (ret) kgsl_mem_entry_detach_process(entry); } err: return ret; err_put_proc_priv: kgsl_put_process_private(dev_priv->device, process); return ret; } Loading @@ -396,6 +406,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; spin_unlock(&entry->priv->mem_lock); kgsl_put_process_private(entry->dev_priv->device, entry->priv); entry->priv = NULL; } Loading Loading @@ -748,11 +759,6 @@ EXPORT_SYMBOL(kgsl_resume_driver); */ static void kgsl_destroy_process_private(struct kref *kref) { struct kgsl_mem_entry *entry = NULL; int next = 0; struct kgsl_process_private *private = container_of(kref, struct kgsl_process_private, refcount); Loading @@ -776,20 +782,6 @@ static void kgsl_destroy_process_private(struct kref *kref) if (private->debug_root) debugfs_remove_recursive(private->debug_root); while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); spin_unlock(&private->mem_lock); if (entry == NULL) break; kgsl_mem_entry_put(entry); /* * Always start back at the beginning, to * ensure all entries are removed, * like list_for_each_entry_safe. */ next = 0; } idr_destroy(&private->mem_idr); kgsl_mmu_putpagetable(private->pagetable); Loading Loading @@ -939,6 +931,7 @@ static int kgsl_release(struct inode *inodep, struct file *filep) struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; Loading Loading @@ -968,6 +961,25 @@ static int kgsl_release(struct inode *inodep, struct file *filep) next = next + 1; } next = 0; while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); spin_unlock(&private->mem_lock); if (entry == NULL) break; /* * If the free pending flag is not set it means that user space * did not free it's reference to this entry, in that case * free a reference to this entry, other references are from * within kgsl so they will be freed eventually by kgsl */ if (entry->dev_priv == dev_priv && !entry->pending_free) { entry->pending_free = 1; kgsl_mem_entry_put(entry); } next = next + 1; } /* * Clean up any to-be-freed entries that belong to this * process and this device. This is done after the context Loading Loading @@ -2736,7 +2748,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, /* echo back flags */ param->flags = entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result) goto error_attach; Loading Loading @@ -3024,7 +3036,7 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, if (result) return result; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result != 0) goto err; Loading Loading @@ -3057,7 +3069,7 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, if (result != 0) goto err; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result != 0) goto err; Loading drivers/gpu/msm/kgsl.h +1 −0 Original line number Diff line number Diff line Loading @@ -202,6 +202,7 @@ struct kgsl_mem_entry { struct kgsl_process_private *priv; /* Initialized to 0, set to 1 when entry is marked for freeing */ int pending_free; struct kgsl_device_private *dev_priv; }; #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT Loading Loading
drivers/gpu/msm/kgsl.c +39 −27 Original line number Diff line number Diff line Loading @@ -343,22 +343,29 @@ kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, */ static int kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, struct kgsl_process_private *process) struct kgsl_device_private *dev_priv) { int id; int ret; struct kgsl_process_private *process = dev_priv->process_priv; ret = kref_get_unless_zero(&process->refcount); if (!ret) return -EBADF; idr_preload(GFP_KERNEL); spin_lock(&process->mem_lock); id = idr_alloc(&process->mem_idr, entry, 1, 0, GFP_NOWAIT); spin_unlock(&process->mem_lock); idr_preload_end(); if (id < 0) return id; if (id < 0) { ret = id; goto err_put_proc_priv; } entry->id = id; entry->priv = process; entry->dev_priv = dev_priv; spin_lock(&process->mem_lock); ret = kgsl_mem_entry_track_gpuaddr(process, entry); Loading @@ -366,14 +373,17 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, idr_remove(&process->mem_idr, entry->id); spin_unlock(&process->mem_lock); if (ret) goto err; goto err_put_proc_priv; /* map the memory after unlocking if gpuaddr has been assigned */ if (entry->memdesc.gpuaddr) { ret = kgsl_mmu_map(process->pagetable, &entry->memdesc); if (ret) kgsl_mem_entry_detach_process(entry); } err: return ret; err_put_proc_priv: kgsl_put_process_private(dev_priv->device, process); return ret; } Loading @@ -396,6 +406,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; spin_unlock(&entry->priv->mem_lock); kgsl_put_process_private(entry->dev_priv->device, entry->priv); entry->priv = NULL; } Loading Loading @@ -748,11 +759,6 @@ EXPORT_SYMBOL(kgsl_resume_driver); */ static void kgsl_destroy_process_private(struct kref *kref) { struct kgsl_mem_entry *entry = NULL; int next = 0; struct kgsl_process_private *private = container_of(kref, struct kgsl_process_private, refcount); Loading @@ -776,20 +782,6 @@ static void kgsl_destroy_process_private(struct kref *kref) if (private->debug_root) debugfs_remove_recursive(private->debug_root); while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); spin_unlock(&private->mem_lock); if (entry == NULL) break; kgsl_mem_entry_put(entry); /* * Always start back at the beginning, to * ensure all entries are removed, * like list_for_each_entry_safe. */ next = 0; } idr_destroy(&private->mem_idr); kgsl_mmu_putpagetable(private->pagetable); Loading Loading @@ -939,6 +931,7 @@ static int kgsl_release(struct inode *inodep, struct file *filep) struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; Loading Loading @@ -968,6 +961,25 @@ static int kgsl_release(struct inode *inodep, struct file *filep) next = next + 1; } next = 0; while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); spin_unlock(&private->mem_lock); if (entry == NULL) break; /* * If the free pending flag is not set it means that user space * did not free it's reference to this entry, in that case * free a reference to this entry, other references are from * within kgsl so they will be freed eventually by kgsl */ if (entry->dev_priv == dev_priv && !entry->pending_free) { entry->pending_free = 1; kgsl_mem_entry_put(entry); } next = next + 1; } /* * Clean up any to-be-freed entries that belong to this * process and this device. This is done after the context Loading Loading @@ -2736,7 +2748,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, /* echo back flags */ param->flags = entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result) goto error_attach; Loading Loading @@ -3024,7 +3036,7 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, if (result) return result; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result != 0) goto err; Loading Loading @@ -3057,7 +3069,7 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, if (result != 0) goto err; result = kgsl_mem_entry_attach_process(entry, private); result = kgsl_mem_entry_attach_process(entry, dev_priv); if (result != 0) goto err; Loading
drivers/gpu/msm/kgsl.h +1 −0 Original line number Diff line number Diff line Loading @@ -202,6 +202,7 @@ struct kgsl_mem_entry { struct kgsl_process_private *priv; /* Initialized to 0, set to 1 when entry is marked for freeing */ int pending_free; struct kgsl_device_private *dev_priv; }; #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT Loading