Merge "msm: kgsl: Make sure USE_CPU_MAP + MAP_USER_MEM work together"
This commit is contained in:
commit
2f088241d7
1 changed files with 65 additions and 80 deletions
|
@ -176,9 +176,10 @@ int kgsl_memfree_find_entry(pid_t ptname, uint64_t *gpuaddr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kgsl_memfree_purge(pid_t ptname, uint64_t gpuaddr,
|
static void kgsl_memfree_purge(struct kgsl_pagetable *pagetable,
|
||||||
uint64_t size)
|
uint64_t gpuaddr, uint64_t size)
|
||||||
{
|
{
|
||||||
|
pid_t ptname = pagetable ? pagetable->name : 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (memfree.list == NULL)
|
if (memfree.list == NULL)
|
||||||
|
@ -342,40 +343,22 @@ kgsl_mem_entry_destroy(struct kref *kref)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
|
EXPORT_SYMBOL(kgsl_mem_entry_destroy);
|
||||||
|
|
||||||
/**
|
/* Allocate a IOVA for memory objects that don't use SVM */
|
||||||
* kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and
|
static int kgsl_mem_entry_track_gpuaddr(struct kgsl_device *device,
|
||||||
* assign it with a gpu address space before insertion
|
struct kgsl_process_private *process,
|
||||||
* @process: the process that owns the memory
|
struct kgsl_mem_entry *entry)
|
||||||
* @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,
|
|
||||||
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
|
* If SVM is enabled for this object then the address needs to be
|
||||||
* gpu address
|
* assigned elsewhere
|
||||||
*/
|
*/
|
||||||
if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
|
if (kgsl_memdesc_use_cpu_map(&entry->memdesc))
|
||||||
if (!entry->memdesc.gpuaddr)
|
return 0;
|
||||||
return 0;
|
|
||||||
} else if (entry->memdesc.gpuaddr) {
|
pagetable = kgsl_memdesc_is_secured(&entry->memdesc) ?
|
||||||
WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n");
|
device->mmu.securepagetable : process->pagetable;
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
if (kgsl_memdesc_is_secured(&entry->memdesc))
|
|
||||||
pagetable = pagetable->mmu->securepagetable;
|
|
||||||
|
|
||||||
return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
|
return kgsl_mmu_get_gpuaddr(pagetable, &entry->memdesc);
|
||||||
}
|
}
|
||||||
|
@ -391,33 +374,25 @@ static void kgsl_mem_entry_commit_process(struct kgsl_mem_entry *entry)
|
||||||
spin_unlock(&entry->priv->mem_lock);
|
spin_unlock(&entry->priv->mem_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* kgsl_mem_entry_attach_process - Attach a mem_entry to its owner process
|
* Attach the memory object to a process by (possibly) getting a GPU address and
|
||||||
* @entry: the memory entry
|
* (possibly) mapping it
|
||||||
* @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.
|
|
||||||
*/
|
*/
|
||||||
int
|
static int kgsl_mem_entry_attach_process(struct kgsl_device *device,
|
||||||
kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
|
struct kgsl_process_private *process,
|
||||||
struct kgsl_device_private *dev_priv)
|
struct kgsl_mem_entry *entry)
|
||||||
{
|
{
|
||||||
int id;
|
int id, ret;
|
||||||
int ret;
|
|
||||||
struct kgsl_process_private *process = dev_priv->process_priv;
|
|
||||||
struct kgsl_pagetable *pagetable = NULL;
|
|
||||||
|
|
||||||
ret = kgsl_process_private_get(process);
|
ret = kgsl_process_private_get(process);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return -EBADF;
|
return -EBADF;
|
||||||
|
|
||||||
ret = kgsl_mem_entry_track_gpuaddr(process, entry);
|
ret = kgsl_mem_entry_track_gpuaddr(device, process, entry);
|
||||||
if (ret)
|
if (ret) {
|
||||||
goto err_put_proc_priv;
|
kgsl_process_private_put(process);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
idr_preload(GFP_KERNEL);
|
idr_preload(GFP_KERNEL);
|
||||||
spin_lock(&process->mem_lock);
|
spin_lock(&process->mem_lock);
|
||||||
|
@ -427,43 +402,40 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
|
||||||
idr_preload_end();
|
idr_preload_end();
|
||||||
|
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
ret = id;
|
if (!kgsl_memdesc_use_cpu_map(&entry->memdesc))
|
||||||
kgsl_mmu_put_gpuaddr(&entry->memdesc);
|
kgsl_mmu_put_gpuaddr(&entry->memdesc);
|
||||||
goto err_put_proc_priv;
|
kgsl_process_private_put(process);
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->id = id;
|
entry->id = id;
|
||||||
entry->priv = process;
|
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) {
|
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)
|
if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT)
|
||||||
ret = kgsl_mmu_sparse_dummy_map(pagetable,
|
ret = kgsl_mmu_sparse_dummy_map(
|
||||||
&entry->memdesc, 0, entry->memdesc.size);
|
entry->memdesc.pagetable,
|
||||||
|
&entry->memdesc, 0,
|
||||||
|
entry->memdesc.size);
|
||||||
else if (entry->memdesc.gpuaddr)
|
else if (entry->memdesc.gpuaddr)
|
||||||
ret = kgsl_mmu_map(pagetable, &entry->memdesc);
|
ret = kgsl_mmu_map(entry->memdesc.pagetable,
|
||||||
|
&entry->memdesc);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
kgsl_mem_entry_detach_process(entry);
|
kgsl_mem_entry_detach_process(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
kgsl_memfree_purge(pagetable ? pagetable->name : 0,
|
kgsl_memfree_purge(entry->memdesc.pagetable, entry->memdesc.gpuaddr,
|
||||||
entry->memdesc.gpuaddr, entry->memdesc.size);
|
entry->memdesc.size);
|
||||||
|
|
||||||
return ret;
|
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 */
|
/* 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)
|
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
|
||||||
{
|
{
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
|
@ -2114,10 +2086,21 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,
|
||||||
entry->memdesc.pagetable = pagetable;
|
entry->memdesc.pagetable = pagetable;
|
||||||
entry->memdesc.size = (uint64_t) size;
|
entry->memdesc.size = (uint64_t) size;
|
||||||
entry->memdesc.useraddr = hostptr;
|
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;
|
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);
|
return memdesc_sg_virt(&entry->memdesc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2367,7 +2350,7 @@ long kgsl_ioctl_gpuobj_import(struct kgsl_device_private *dev_priv,
|
||||||
|
|
||||||
param->flags = entry->memdesc.flags;
|
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)
|
if (ret)
|
||||||
goto unmap;
|
goto unmap;
|
||||||
|
|
||||||
|
@ -2671,7 +2654,8 @@ long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
|
||||||
/* echo back flags */
|
/* echo back flags */
|
||||||
param->flags = (unsigned int) entry->memdesc.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)
|
if (result)
|
||||||
goto error_attach;
|
goto error_attach;
|
||||||
|
|
||||||
|
@ -3068,7 +3052,7 @@ static struct kgsl_mem_entry *gpumem_alloc_entry(
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto err;
|
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) {
|
if (ret != 0) {
|
||||||
kgsl_sharedmem_free(&entry->memdesc);
|
kgsl_sharedmem_free(&entry->memdesc);
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -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,
|
long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
|
||||||
unsigned int cmd, void *data)
|
unsigned int cmd, void *data)
|
||||||
{
|
{
|
||||||
|
struct kgsl_process_private *private = dev_priv->process_priv;
|
||||||
struct kgsl_sparse_virt_alloc *param = data;
|
struct kgsl_sparse_virt_alloc *param = data;
|
||||||
struct kgsl_mem_entry *entry;
|
struct kgsl_mem_entry *entry;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -3354,7 +3339,7 @@ long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
|
||||||
spin_lock_init(&entry->bind_lock);
|
spin_lock_init(&entry->bind_lock);
|
||||||
entry->bind_tree = RB_ROOT;
|
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) {
|
if (ret) {
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4040,8 +4025,8 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
kgsl_memfree_purge(private->pagetable ? private->pagetable->name : 0,
|
kgsl_memfree_purge(private->pagetable, entry->memdesc.gpuaddr,
|
||||||
entry->memdesc.gpuaddr, entry->memdesc.size);
|
entry->memdesc.size);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue