Loading drivers/gpu/msm/kgsl.c +65 −80 Original line number Diff line number Diff line Loading @@ -176,9 +176,10 @@ int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr, return 0; } static void kgsl_memfree_purge(pid_t ptname, uint64_t gpuaddr, uint64_t size) static void kgsl_memfree_purge(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size) { pid_t ptname = pagetable ? pagetable->name : 0; int i; if (memfree.list == NULL) Loading Loading @@ -342,40 +343,22 @@ kgsl_mem_entry_destroy(struct kref *kref) } EXPORT_SYMBOL(kgsl_mem_entry_destroy); /** * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and * assign it with a gpu address space before insertion * @process: the process that owns the memory * @entry: the memory entry * * @returns - 0 on succcess else error code * * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. * The assignment of gpu address and insertion into list needs to * happen with the memory lock held to avoid race conditions between * gpu address being selected and some other thread looking through the * rb list in search of memory based on gpuaddr * This function should be called with processes memory spinlock held */ static int kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, /* Allocate a IOVA for memory objects that don't use SVM */ static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device, struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { struct kgsl_pagetable *pagetable = process->pagetable; struct kgsl_pagetable *pagetable; /* * If cpu=gpu map is used then caller needs to set the * gpu address * If SVM is enabled for this object then the address needs to be * assigned elsewhere */ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { if (!entry->memdesc.gpuaddr) if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) return 0; } else if (entry->memdesc.gpuaddr) { WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); return -EINVAL; } if (kgsl_memdesc_is_secured(&entry->memdesc)) pagetable = pagetable->mmu->securepagetable; pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ? device->mmu.securepagetable : process->pagetable; return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); } Loading @@ -391,33 +374,25 @@ static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) spin_unlock(&entry->priv->mem_lock); } /** * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process * @entry: the memory entry * @process: the owner process * * Attach a newly created mem_entry to its owner process so that * it can be found later. The mem_entry will be added to mem_idr and have * its 'id' field assigned. * * @returns - 0 on success or error code on failure. /* * Attach the memory object to a process by (possibly) getting a GPU address and * (possibly) mapping it */ int kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, struct kgsl_device_private *dev_priv) static int kgsl_mem_entry_attach_process(struct kgsl_device *device, struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { int id; int ret; struct kgsl_process_private *process = dev_priv->process_priv; struct kgsl_pagetable *pagetable = NULL; int id, ret; ret = kgsl_process_private_get(process); if (!ret) return -EBADF; ret = kgsl_mem_entry_track_gpuaddr(process, entry); if (ret) goto err_put_proc_priv; ret = kgsl_mem_entry_track_gpuaddr(device, process, entry); if (ret) { kgsl_process_private_put(process); return ret; } idr_preload(GFP_KERNEL); spin_lock(&process->mem_lock); Loading @@ -427,43 +402,40 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, idr_preload_end(); if (id < 0) { ret = id; if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) kgsl_mmu_put_gpuaddr(&entry->memdesc); goto err_put_proc_priv; kgsl_process_private_put(process); return id; } entry->id = id; entry->priv = process; /* map the memory after unlocking if gpuaddr has been assigned */ /* * Map the memory if a GPU address is already assigned, either through * kgsl_mem_entry_track_gpuaddr() or via some other SVM process */ if (entry->memdesc.gpuaddr) { pagetable = process->pagetable; if (kgsl_memdesc_is_secured(&entry->memdesc)) pagetable = pagetable->mmu->securepagetable; entry->memdesc.pagetable = pagetable; if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT) ret = kgsl_mmu_sparse_dummy_map(pagetable, &entry->memdesc, 0, entry->memdesc.size); ret = kgsl_mmu_sparse_dummy_map( entry->memdesc.pagetable, &entry->memdesc, 0, entry->memdesc.size); else if (entry->memdesc.gpuaddr) ret = kgsl_mmu_map(pagetable, &entry->memdesc); ret = kgsl_mmu_map(entry->memdesc.pagetable, &entry->memdesc); if (ret) kgsl_mem_entry_detach_process(entry); } kgsl_memfree_purge(pagetable ? pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size); kgsl_memfree_purge(entry->memdesc.pagetable, entry->memdesc.gpuaddr, entry->memdesc.size); return ret; err_put_proc_priv: kgsl_process_private_put(process); return ret; } /* Detach a memory entry from a process and unmap it from the MMU */ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) { unsigned int type; Loading Loading @@ -2114,10 +2086,21 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.pagetable = pagetable; entry->memdesc.size = (uint64_t) size; entry->memdesc.useraddr = hostptr; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { int ret; /* Register the address in the database */ ret = kgsl_mmu_set_svm_region(pagetable, (uint64_t) entry->memdesc.useraddr, (uint64_t) size); if (ret) return ret; entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; } return memdesc_sg_virt(&entry->memdesc, NULL); } Loading Loading @@ -2367,7 +2350,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, param->flags = entry->memdesc.flags; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret) goto unmap; Loading Loading @@ -2671,7 +2654,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, /* echo back flags */ param->flags = (unsigned int) entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, dev_priv); result = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (result) goto error_attach; Loading Loading @@ -3068,7 +3052,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( if (ret != 0) goto err; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret != 0) { kgsl_sharedmem_free(&entry->memdesc); goto err; Loading Loading @@ -3334,6 +3318,7 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv, long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_sparse_virt_alloc *param = data; struct kgsl_mem_entry *entry; int ret; Loading @@ -3354,7 +3339,7 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, spin_lock_init(&entry->bind_lock); entry->bind_tree = RB_ROOT; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret) { kfree(entry); return ret; Loading Loading @@ -4040,8 +4025,8 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, return ret; } kgsl_memfree_purge(private->pagetable ? private->pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size); kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr, entry->memdesc.size); return addr; } Loading Loading
drivers/gpu/msm/kgsl.c +65 −80 Original line number Diff line number Diff line Loading @@ -176,9 +176,10 @@ int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr, return 0; } static void kgsl_memfree_purge(pid_t ptname, uint64_t gpuaddr, uint64_t size) static void kgsl_memfree_purge(struct kgsl_pagetable *pagetable, uint64_t gpuaddr, uint64_t size) { pid_t ptname = pagetable ? pagetable->name : 0; int i; if (memfree.list == NULL) Loading Loading @@ -342,40 +343,22 @@ kgsl_mem_entry_destroy(struct kref *kref) } EXPORT_SYMBOL(kgsl_mem_entry_destroy); /** * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and * assign it with a gpu address space before insertion * @process: the process that owns the memory * @entry: the memory entry * * @returns - 0 on succcess else error code * * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. * The assignment of gpu address and insertion into list needs to * happen with the memory lock held to avoid race conditions between * gpu address being selected and some other thread looking through the * rb list in search of memory based on gpuaddr * This function should be called with processes memory spinlock held */ static int kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, /* Allocate a IOVA for memory objects that don't use SVM */ static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device, struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { struct kgsl_pagetable *pagetable = process->pagetable; struct kgsl_pagetable *pagetable; /* * If cpu=gpu map is used then caller needs to set the * gpu address * If SVM is enabled for this object then the address needs to be * assigned elsewhere */ if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { if (!entry->memdesc.gpuaddr) if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) return 0; } else if (entry->memdesc.gpuaddr) { WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); return -EINVAL; } if (kgsl_memdesc_is_secured(&entry->memdesc)) pagetable = pagetable->mmu->securepagetable; pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ? device->mmu.securepagetable : process->pagetable; return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc); } Loading @@ -391,33 +374,25 @@ static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry) spin_unlock(&entry->priv->mem_lock); } /** * kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process * @entry: the memory entry * @process: the owner process * * Attach a newly created mem_entry to its owner process so that * it can be found later. The mem_entry will be added to mem_idr and have * its 'id' field assigned. * * @returns - 0 on success or error code on failure. /* * Attach the memory object to a process by (possibly) getting a GPU address and * (possibly) mapping it */ int kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, struct kgsl_device_private *dev_priv) static int kgsl_mem_entry_attach_process(struct kgsl_device *device, struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { int id; int ret; struct kgsl_process_private *process = dev_priv->process_priv; struct kgsl_pagetable *pagetable = NULL; int id, ret; ret = kgsl_process_private_get(process); if (!ret) return -EBADF; ret = kgsl_mem_entry_track_gpuaddr(process, entry); if (ret) goto err_put_proc_priv; ret = kgsl_mem_entry_track_gpuaddr(device, process, entry); if (ret) { kgsl_process_private_put(process); return ret; } idr_preload(GFP_KERNEL); spin_lock(&process->mem_lock); Loading @@ -427,43 +402,40 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, idr_preload_end(); if (id < 0) { ret = id; if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) kgsl_mmu_put_gpuaddr(&entry->memdesc); goto err_put_proc_priv; kgsl_process_private_put(process); return id; } entry->id = id; entry->priv = process; /* map the memory after unlocking if gpuaddr has been assigned */ /* * Map the memory if a GPU address is already assigned, either through * kgsl_mem_entry_track_gpuaddr() or via some other SVM process */ if (entry->memdesc.gpuaddr) { pagetable = process->pagetable; if (kgsl_memdesc_is_secured(&entry->memdesc)) pagetable = pagetable->mmu->securepagetable; entry->memdesc.pagetable = pagetable; if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT) ret = kgsl_mmu_sparse_dummy_map(pagetable, &entry->memdesc, 0, entry->memdesc.size); ret = kgsl_mmu_sparse_dummy_map( entry->memdesc.pagetable, &entry->memdesc, 0, entry->memdesc.size); else if (entry->memdesc.gpuaddr) ret = kgsl_mmu_map(pagetable, &entry->memdesc); ret = kgsl_mmu_map(entry->memdesc.pagetable, &entry->memdesc); if (ret) kgsl_mem_entry_detach_process(entry); } kgsl_memfree_purge(pagetable ? pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size); kgsl_memfree_purge(entry->memdesc.pagetable, entry->memdesc.gpuaddr, entry->memdesc.size); return ret; err_put_proc_priv: kgsl_process_private_put(process); return ret; } /* Detach a memory entry from a process and unmap it from the MMU */ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) { unsigned int type; Loading Loading @@ -2114,10 +2086,21 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.pagetable = pagetable; entry->memdesc.size = (uint64_t) size; entry->memdesc.useraddr = hostptr; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; entry->memdesc.flags |= KGSL_MEMFLAGS_USERMEM_ADDR; if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { int ret; /* Register the address in the database */ ret = kgsl_mmu_set_svm_region(pagetable, (uint64_t) entry->memdesc.useraddr, (uint64_t) size); if (ret) return ret; entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; } return memdesc_sg_virt(&entry->memdesc, NULL); } Loading Loading @@ -2367,7 +2350,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv, param->flags = entry->memdesc.flags; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret) goto unmap; Loading Loading @@ -2671,7 +2654,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, /* echo back flags */ param->flags = (unsigned int) entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, dev_priv); result = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (result) goto error_attach; Loading Loading @@ -3068,7 +3052,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry( if (ret != 0) goto err; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret != 0) { kgsl_sharedmem_free(&entry->memdesc); goto err; Loading Loading @@ -3334,6 +3318,7 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv, long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) { struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_sparse_virt_alloc *param = data; struct kgsl_mem_entry *entry; int ret; Loading @@ -3354,7 +3339,7 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv, spin_lock_init(&entry->bind_lock); entry->bind_tree = RB_ROOT; ret = kgsl_mem_entry_attach_process(entry, dev_priv); ret = kgsl_mem_entry_attach_process(dev_priv->device, private, entry); if (ret) { kfree(entry); return ret; Loading Loading @@ -4040,8 +4025,8 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, return ret; } kgsl_memfree_purge(private->pagetable ? private->pagetable->name : 0, entry->memdesc.gpuaddr, entry->memdesc.size); kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr, entry->memdesc.size); return addr; } Loading