Loading drivers/gpu/msm/kgsl.c +141 −120 Original line number Diff line number Diff line Loading @@ -860,114 +860,165 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) return private; } /** * kgsl_process_private_new() - Helper function to search for process private * Returns: Pointer to the found/newly created private struct */ static struct kgsl_process_private *kgsl_process_private_new(void) static struct kgsl_process_private *kgsl_process_private_new( struct kgsl_device *device) { struct kgsl_process_private *private; pid_t tgid = task_tgid_nr(current); /* Search in the process list */ mutex_lock(&kgsl_driver.process_mutex); list_for_each_entry(private, &kgsl_driver.process_list, list) { if (private->pid == task_tgid_nr(current)) { if (private->pid == tgid) { if (!kgsl_process_private_get(private)) private = NULL; goto done; private = ERR_PTR(-EINVAL); return private; } } /* no existing process private found for this dev_priv, create one */ /* Create a new object */ private = kzalloc(sizeof(struct kgsl_process_private), GFP_KERNEL); if (private == NULL) goto done; return ERR_PTR(-ENOMEM); kref_init(&private->refcount); private->pid = task_tgid_nr(current); private->pid = tgid; get_task_comm(private->comm, current->group_leader); private->mem_rb = RB_ROOT; spin_lock_init(&private->mem_lock); mutex_init(&private->process_private_mutex); /* Add the newly created process struct obj to the process list */ list_add(&private->list, &kgsl_driver.process_list); done: mutex_unlock(&kgsl_driver.process_mutex); spin_lock_init(&private->syncsource_lock); idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); /* Allocate a pagetable for the new process object */ if (kgsl_mmu_enabled()) { private->pagetable = kgsl_mmu_getpagetable(&device->mmu, tgid); if (private->pagetable == NULL) { idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); kfree(private); private = ERR_PTR(-ENOMEM); } } return private; } /** * kgsl_detach_process_private() - Remove a process private from the process * private list and free things in the process private that relate to * the process id in order to allow next open from same process create * a new process private * @private: Pointer to process private to detach static void process_release_memory(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private) { struct kgsl_mem_entry *entry; int next = 0; while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); if (entry == NULL) { spin_unlock(&private->mem_lock); 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 */ static void kgsl_detach_process_private(struct kgsl_process_private *private) if (entry->dev_priv == dev_priv && !entry->pending_free) { entry->pending_free = 1; spin_unlock(&private->mem_lock); kgsl_mem_entry_put(entry); } else { spin_unlock(&private->mem_lock); } next = next + 1; } } static void process_release_sync_sources(struct kgsl_process_private *private) { mutex_lock(&kgsl_driver.process_mutex); list_del(&private->list); mutex_unlock(&kgsl_driver.process_mutex); struct kgsl_syncsource *syncsource; int next = 0; if (private->kobj.state_in_sysfs) kgsl_process_uninit_sysfs(private); debugfs_remove_recursive(private->debug_root); while (1) { spin_lock(&private->syncsource_lock); syncsource = idr_get_next(&private->syncsource_idr, &next); spin_unlock(&private->syncsource_lock); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } } /** * kgsl_get_process_private() - Used to find the process private structure * @cur_dev_priv: Current device pointer * Finds or creates a new porcess private structire and initializes its members * Returns: Pointer to the private process struct obj found/created or * NULL if pagetable creation for this process private obj failed. */ static struct kgsl_process_private * kgsl_get_process_private(struct kgsl_device *device) static void kgsl_process_private_close(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private) { struct kgsl_process_private *private; mutex_lock(&kgsl_driver.process_mutex); private = kgsl_process_private_new(); /* * If this is the last file on the process take down the debug * directories and garbage collect any outstanding resources */ if (!private) return NULL; if (--private->fd_count == 0) { kgsl_process_uninit_sysfs(private); debugfs_remove_recursive(private->debug_root); mutex_lock(&private->process_private_mutex); process_release_memory(dev_priv, private); process_release_sync_sources(private); if (test_bit(KGSL_PROCESS_INIT, &private->priv)) goto done; /* Remove the process struct from the master list */ list_del(&private->list); } get_task_comm(private->comm, current->group_leader); kgsl_process_private_put(private); mutex_unlock(&kgsl_driver.process_mutex); } private->mem_rb = RB_ROOT; idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); static struct kgsl_process_private *kgsl_process_private_open( struct kgsl_device *device) { struct kgsl_process_private *private; if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; mutex_lock(&kgsl_driver.process_mutex); private = kgsl_process_private_new(device); pt_name = task_tgid_nr(current); private->pagetable = kgsl_mmu_getpagetable(&device->mmu, pt_name); if (private->pagetable == NULL) goto error; if (IS_ERR(private)) goto done; /* * If this is a new process create the debug directories and add it to * the process list */ if (private->fd_count++ == 0) { int ret = kgsl_process_init_sysfs(device, private); if (ret) { kgsl_process_private_put(private); private = ERR_PTR(ret); goto done; } if (kgsl_process_init_sysfs(device, private)) goto error; if (kgsl_process_init_debugfs(private)) goto error; ret = kgsl_process_init_debugfs(private); if (ret) { kgsl_process_uninit_sysfs(private); kgsl_process_private_put(private); private = ERR_PTR(ret); goto done; } set_bit(KGSL_PROCESS_INIT, &private->priv); list_add(&private->list, &kgsl_driver.process_list); } done: mutex_unlock(&private->process_private_mutex); mutex_unlock(&kgsl_driver.process_mutex); return private; error: mutex_unlock(&private->process_private_mutex); kgsl_detach_process_private(private); kgsl_process_private_put(private); return NULL; } static int kgsl_close_device(struct kgsl_device *device) Loading @@ -992,30 +1043,12 @@ static int kgsl_close_device(struct kgsl_device *device) } static int kgsl_release(struct inode *inodep, struct file *filep) static void device_release_contexts(struct kgsl_device_private *dev_priv) { int result = 0; struct kgsl_device_private *dev_priv = filep->private_data; struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_syncsource *syncsource; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; next = 0; while (1) { syncsource = idr_get_next(&private->syncsource_idr, &next); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } next = 0; while (1) { read_lock(&device->context_lock); context = idr_get_next(&device->context_idr, &next); Loading @@ -1038,39 +1071,27 @@ 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); if (entry == NULL) { spin_unlock(&private->mem_lock); 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; spin_unlock(&private->mem_lock); kgsl_mem_entry_put(entry); } else { spin_unlock(&private->mem_lock); } next = next + 1; } result = kgsl_close_device(device); static int kgsl_release(struct inode *inodep, struct file *filep) { struct kgsl_device_private *dev_priv = filep->private_data; struct kgsl_device *device = dev_priv->device; int result; kfree(dev_priv); filep->private_data = NULL; kgsl_detach_process_private(private); /* Release the contexts for the file */ device_release_contexts(dev_priv); kgsl_process_private_put(private); /* Close down the process wide resources for the file */ kgsl_process_private_close(dev_priv, dev_priv->process_priv); kfree(dev_priv); result = kgsl_close_device(device); pm_runtime_put(&device->pdev->dev); return result; } Loading Loading @@ -1150,10 +1171,10 @@ static int kgsl_open(struct inode *inodep, struct file *filep) * after the first start so that the global pagetable mappings * are set up before we create the per-process pagetable. */ dev_priv->process_priv = kgsl_get_process_private(device); if (dev_priv->process_priv == NULL) { dev_priv->process_priv = kgsl_process_private_open(device); if (IS_ERR(dev_priv->process_priv)) { result = PTR_ERR(dev_priv->process_priv); kgsl_close_device(device); result = -ENOMEM; goto err; } Loading drivers/gpu/msm/kgsl_device.h +4 −8 Original line number Diff line number Diff line Loading @@ -479,7 +479,6 @@ struct kgsl_context { * @comm: task name of the process * @mem_lock: Spinlock to protect the process memory lists * @refcount: kref object for reference counting the process * @process_private_mutex: Mutex to synchronize access to the process struct * @mem_rb: RB tree node for the memory owned by this process * @idr: Iterator for assigning IDs to memory allocations * @pagetable: Pointer to the pagetable owned by this process Loading @@ -487,31 +486,28 @@ struct kgsl_context { * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process * @syncsource_idr: sync sources created by this process * @syncsource_lock: Spinlock to protect the syncsource idr * @fd_count: Counter for the number of FDs for this process */ struct kgsl_process_private { unsigned long priv; pid_t pid; char comm[TASK_COMM_LEN]; spinlock_t mem_lock; /* General refcount for process private struct obj */ struct kref refcount; /* Mutex to synchronize access to each process_private struct obj */ struct mutex process_private_mutex; struct rb_root mem_rb; struct idr mem_idr; struct kgsl_pagetable *pagetable; struct list_head list; struct kobject kobj; struct dentry *debug_root; struct { unsigned int cur; unsigned int max; } stats[KGSL_MEM_ENTRY_MAX]; struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; }; /** Loading drivers/gpu/msm/kgsl_sync.c +13 −9 Original line number Diff line number Diff line Loading @@ -476,8 +476,12 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, goto out; } mutex_lock(&private->process_private_mutex); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_KERNEL); idr_preload(GFP_KERNEL); spin_lock(&private->syncsource_lock); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_NOWAIT); spin_unlock(&private->syncsource_lock); idr_preload_end(); if (id > 0) { kref_init(&syncsource->refcount); syncsource->id = id; Loading @@ -488,7 +492,7 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, } else { ret = id; } mutex_unlock(&private->process_private_mutex); out: if (ret) { if (syncsource && syncsource->oneshot) Loading @@ -505,13 +509,13 @@ kgsl_syncsource_get(struct kgsl_process_private *private, int id) int result = 0; struct kgsl_syncsource *syncsource = NULL; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); syncsource = idr_find(&private->syncsource_idr, id); if (syncsource) result = kref_get_unless_zero(&syncsource->refcount); mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); return result ? syncsource : NULL; } Loading @@ -524,13 +528,13 @@ static void kgsl_syncsource_destroy(struct kref *kref) struct kgsl_process_private *private = syncsource->private; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); if (syncsource->id != 0) { idr_remove(&private->syncsource_idr, syncsource->id); syncsource->id = 0; } oneshot_timeline_destroy(syncsource->oneshot); mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); kfree(syncsource); } Loading @@ -556,10 +560,10 @@ long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, private = syncsource->private; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); idr_remove(&private->syncsource_idr, param->id); syncsource->id = 0; mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); /* put reference from syncsource creation */ kgsl_syncsource_put(syncsource); Loading Loading
drivers/gpu/msm/kgsl.c +141 −120 Original line number Diff line number Diff line Loading @@ -860,114 +860,165 @@ struct kgsl_process_private *kgsl_process_private_find(pid_t pid) return private; } /** * kgsl_process_private_new() - Helper function to search for process private * Returns: Pointer to the found/newly created private struct */ static struct kgsl_process_private *kgsl_process_private_new(void) static struct kgsl_process_private *kgsl_process_private_new( struct kgsl_device *device) { struct kgsl_process_private *private; pid_t tgid = task_tgid_nr(current); /* Search in the process list */ mutex_lock(&kgsl_driver.process_mutex); list_for_each_entry(private, &kgsl_driver.process_list, list) { if (private->pid == task_tgid_nr(current)) { if (private->pid == tgid) { if (!kgsl_process_private_get(private)) private = NULL; goto done; private = ERR_PTR(-EINVAL); return private; } } /* no existing process private found for this dev_priv, create one */ /* Create a new object */ private = kzalloc(sizeof(struct kgsl_process_private), GFP_KERNEL); if (private == NULL) goto done; return ERR_PTR(-ENOMEM); kref_init(&private->refcount); private->pid = task_tgid_nr(current); private->pid = tgid; get_task_comm(private->comm, current->group_leader); private->mem_rb = RB_ROOT; spin_lock_init(&private->mem_lock); mutex_init(&private->process_private_mutex); /* Add the newly created process struct obj to the process list */ list_add(&private->list, &kgsl_driver.process_list); done: mutex_unlock(&kgsl_driver.process_mutex); spin_lock_init(&private->syncsource_lock); idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); /* Allocate a pagetable for the new process object */ if (kgsl_mmu_enabled()) { private->pagetable = kgsl_mmu_getpagetable(&device->mmu, tgid); if (private->pagetable == NULL) { idr_destroy(&private->mem_idr); idr_destroy(&private->syncsource_idr); kfree(private); private = ERR_PTR(-ENOMEM); } } return private; } /** * kgsl_detach_process_private() - Remove a process private from the process * private list and free things in the process private that relate to * the process id in order to allow next open from same process create * a new process private * @private: Pointer to process private to detach static void process_release_memory(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private) { struct kgsl_mem_entry *entry; int next = 0; while (1) { spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); if (entry == NULL) { spin_unlock(&private->mem_lock); 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 */ static void kgsl_detach_process_private(struct kgsl_process_private *private) if (entry->dev_priv == dev_priv && !entry->pending_free) { entry->pending_free = 1; spin_unlock(&private->mem_lock); kgsl_mem_entry_put(entry); } else { spin_unlock(&private->mem_lock); } next = next + 1; } } static void process_release_sync_sources(struct kgsl_process_private *private) { mutex_lock(&kgsl_driver.process_mutex); list_del(&private->list); mutex_unlock(&kgsl_driver.process_mutex); struct kgsl_syncsource *syncsource; int next = 0; if (private->kobj.state_in_sysfs) kgsl_process_uninit_sysfs(private); debugfs_remove_recursive(private->debug_root); while (1) { spin_lock(&private->syncsource_lock); syncsource = idr_get_next(&private->syncsource_idr, &next); spin_unlock(&private->syncsource_lock); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } } /** * kgsl_get_process_private() - Used to find the process private structure * @cur_dev_priv: Current device pointer * Finds or creates a new porcess private structire and initializes its members * Returns: Pointer to the private process struct obj found/created or * NULL if pagetable creation for this process private obj failed. */ static struct kgsl_process_private * kgsl_get_process_private(struct kgsl_device *device) static void kgsl_process_private_close(struct kgsl_device_private *dev_priv, struct kgsl_process_private *private) { struct kgsl_process_private *private; mutex_lock(&kgsl_driver.process_mutex); private = kgsl_process_private_new(); /* * If this is the last file on the process take down the debug * directories and garbage collect any outstanding resources */ if (!private) return NULL; if (--private->fd_count == 0) { kgsl_process_uninit_sysfs(private); debugfs_remove_recursive(private->debug_root); mutex_lock(&private->process_private_mutex); process_release_memory(dev_priv, private); process_release_sync_sources(private); if (test_bit(KGSL_PROCESS_INIT, &private->priv)) goto done; /* Remove the process struct from the master list */ list_del(&private->list); } get_task_comm(private->comm, current->group_leader); kgsl_process_private_put(private); mutex_unlock(&kgsl_driver.process_mutex); } private->mem_rb = RB_ROOT; idr_init(&private->mem_idr); idr_init(&private->syncsource_idr); static struct kgsl_process_private *kgsl_process_private_open( struct kgsl_device *device) { struct kgsl_process_private *private; if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; mutex_lock(&kgsl_driver.process_mutex); private = kgsl_process_private_new(device); pt_name = task_tgid_nr(current); private->pagetable = kgsl_mmu_getpagetable(&device->mmu, pt_name); if (private->pagetable == NULL) goto error; if (IS_ERR(private)) goto done; /* * If this is a new process create the debug directories and add it to * the process list */ if (private->fd_count++ == 0) { int ret = kgsl_process_init_sysfs(device, private); if (ret) { kgsl_process_private_put(private); private = ERR_PTR(ret); goto done; } if (kgsl_process_init_sysfs(device, private)) goto error; if (kgsl_process_init_debugfs(private)) goto error; ret = kgsl_process_init_debugfs(private); if (ret) { kgsl_process_uninit_sysfs(private); kgsl_process_private_put(private); private = ERR_PTR(ret); goto done; } set_bit(KGSL_PROCESS_INIT, &private->priv); list_add(&private->list, &kgsl_driver.process_list); } done: mutex_unlock(&private->process_private_mutex); mutex_unlock(&kgsl_driver.process_mutex); return private; error: mutex_unlock(&private->process_private_mutex); kgsl_detach_process_private(private); kgsl_process_private_put(private); return NULL; } static int kgsl_close_device(struct kgsl_device *device) Loading @@ -992,30 +1043,12 @@ static int kgsl_close_device(struct kgsl_device *device) } static int kgsl_release(struct inode *inodep, struct file *filep) static void device_release_contexts(struct kgsl_device_private *dev_priv) { int result = 0; struct kgsl_device_private *dev_priv = filep->private_data; struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_device *device = dev_priv->device; struct kgsl_context *context; struct kgsl_syncsource *syncsource; struct kgsl_mem_entry *entry; int next = 0; filep->private_data = NULL; next = 0; while (1) { syncsource = idr_get_next(&private->syncsource_idr, &next); if (syncsource == NULL) break; kgsl_syncsource_put(syncsource); next = next + 1; } next = 0; while (1) { read_lock(&device->context_lock); context = idr_get_next(&device->context_idr, &next); Loading @@ -1038,39 +1071,27 @@ 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); if (entry == NULL) { spin_unlock(&private->mem_lock); 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; spin_unlock(&private->mem_lock); kgsl_mem_entry_put(entry); } else { spin_unlock(&private->mem_lock); } next = next + 1; } result = kgsl_close_device(device); static int kgsl_release(struct inode *inodep, struct file *filep) { struct kgsl_device_private *dev_priv = filep->private_data; struct kgsl_device *device = dev_priv->device; int result; kfree(dev_priv); filep->private_data = NULL; kgsl_detach_process_private(private); /* Release the contexts for the file */ device_release_contexts(dev_priv); kgsl_process_private_put(private); /* Close down the process wide resources for the file */ kgsl_process_private_close(dev_priv, dev_priv->process_priv); kfree(dev_priv); result = kgsl_close_device(device); pm_runtime_put(&device->pdev->dev); return result; } Loading Loading @@ -1150,10 +1171,10 @@ static int kgsl_open(struct inode *inodep, struct file *filep) * after the first start so that the global pagetable mappings * are set up before we create the per-process pagetable. */ dev_priv->process_priv = kgsl_get_process_private(device); if (dev_priv->process_priv == NULL) { dev_priv->process_priv = kgsl_process_private_open(device); if (IS_ERR(dev_priv->process_priv)) { result = PTR_ERR(dev_priv->process_priv); kgsl_close_device(device); result = -ENOMEM; goto err; } Loading
drivers/gpu/msm/kgsl_device.h +4 −8 Original line number Diff line number Diff line Loading @@ -479,7 +479,6 @@ struct kgsl_context { * @comm: task name of the process * @mem_lock: Spinlock to protect the process memory lists * @refcount: kref object for reference counting the process * @process_private_mutex: Mutex to synchronize access to the process struct * @mem_rb: RB tree node for the memory owned by this process * @idr: Iterator for assigning IDs to memory allocations * @pagetable: Pointer to the pagetable owned by this process Loading @@ -487,31 +486,28 @@ struct kgsl_context { * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process * @syncsource_idr: sync sources created by this process * @syncsource_lock: Spinlock to protect the syncsource idr * @fd_count: Counter for the number of FDs for this process */ struct kgsl_process_private { unsigned long priv; pid_t pid; char comm[TASK_COMM_LEN]; spinlock_t mem_lock; /* General refcount for process private struct obj */ struct kref refcount; /* Mutex to synchronize access to each process_private struct obj */ struct mutex process_private_mutex; struct rb_root mem_rb; struct idr mem_idr; struct kgsl_pagetable *pagetable; struct list_head list; struct kobject kobj; struct dentry *debug_root; struct { unsigned int cur; unsigned int max; } stats[KGSL_MEM_ENTRY_MAX]; struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; }; /** Loading
drivers/gpu/msm/kgsl_sync.c +13 −9 Original line number Diff line number Diff line Loading @@ -476,8 +476,12 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, goto out; } mutex_lock(&private->process_private_mutex); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_KERNEL); idr_preload(GFP_KERNEL); spin_lock(&private->syncsource_lock); id = idr_alloc(&private->syncsource_idr, syncsource, 1, 0, GFP_NOWAIT); spin_unlock(&private->syncsource_lock); idr_preload_end(); if (id > 0) { kref_init(&syncsource->refcount); syncsource->id = id; Loading @@ -488,7 +492,7 @@ long kgsl_ioctl_syncsource_create(struct kgsl_device_private *dev_priv, } else { ret = id; } mutex_unlock(&private->process_private_mutex); out: if (ret) { if (syncsource && syncsource->oneshot) Loading @@ -505,13 +509,13 @@ kgsl_syncsource_get(struct kgsl_process_private *private, int id) int result = 0; struct kgsl_syncsource *syncsource = NULL; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); syncsource = idr_find(&private->syncsource_idr, id); if (syncsource) result = kref_get_unless_zero(&syncsource->refcount); mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); return result ? syncsource : NULL; } Loading @@ -524,13 +528,13 @@ static void kgsl_syncsource_destroy(struct kref *kref) struct kgsl_process_private *private = syncsource->private; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); if (syncsource->id != 0) { idr_remove(&private->syncsource_idr, syncsource->id); syncsource->id = 0; } oneshot_timeline_destroy(syncsource->oneshot); mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); kfree(syncsource); } Loading @@ -556,10 +560,10 @@ long kgsl_ioctl_syncsource_destroy(struct kgsl_device_private *dev_priv, private = syncsource->private; mutex_lock(&private->process_private_mutex); spin_lock(&private->syncsource_lock); idr_remove(&private->syncsource_idr, param->id); syncsource->id = 0; mutex_unlock(&private->process_private_mutex); spin_unlock(&private->syncsource_lock); /* put reference from syncsource creation */ kgsl_syncsource_put(syncsource); Loading