From 460c0a81bb527604f1093f70739f43b9334e6d9b Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:03 -0600 Subject: [PATCH 1/4] msm: kgsl: Use a simpler algorithm to find SVM addresses Currently the driver uses some unexported functions from mm to search for a virtual address that works for both the GPU and CPU. This method had some benefit for 32 bit applications that used a lot of the CPU virtual address space but was generally overkill for 64 bit applications. Instead, use a simpler approach that uses available symbols. For SVM addresses, walk backwards through the SVM region looking for gaps in the GPU address space. For each one, check if there are any CPU mappings that intersect it. If not, the address can be used for SVM. The worst case scenario for this would be to try to find space for a page in a 32 bit process that had a lot of other pages already mapped for the CPU. This is not as bad for 64 bit since the SVM has its own special region and the CPU virtual addresses are more unlikely to intersect with it so the only conflicts will come from SVM regions that have been recently freed but not yet unmapped from the GPU. Change-Id: Ic0dedbadb59501a86e018f21bd477e5c18664e5e Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl.c | 243 ++++++++++++++--------------------------- 1 file changed, 83 insertions(+), 160 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index c0d30706053a..9d3460383830 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4551,169 +4551,94 @@ static unsigned long _gpu_set_svm_region(struct kgsl_process_private *private, return addr; } -static unsigned long _gpu_find_svm(struct kgsl_process_private *private, - unsigned long start, unsigned long end, unsigned long len, - unsigned int align) +static unsigned long get_align(struct kgsl_mem_entry *entry) { - uint64_t addr = kgsl_mmu_find_svm_region(private->pagetable, - (uint64_t) start, (uint64_t)end, (uint64_t) len, align); + int bit = kgsl_memdesc_get_align(&entry->memdesc); - WARN(!IS_ERR_VALUE((unsigned long)addr) && (addr > ULONG_MAX), - "Couldn't find range\n"); + if (bit >= ilog2(SZ_2M)) + return SZ_2M; + else if (bit >= ilog2(SZ_1M)) + return SZ_1M; + else if (bit >= ilog2(SZ_64K)) + return SZ_64K; - return (unsigned long) addr; + return SZ_4K; } -/* Search top down in the CPU VM region for a free address */ -static unsigned long _cpu_get_unmapped_area(unsigned long bottom, - unsigned long top, unsigned long len, unsigned long align) -{ - struct vm_unmapped_area_info info; - unsigned long addr, err; - - info.flags = VM_UNMAPPED_AREA_TOPDOWN; - info.low_limit = bottom; - info.high_limit = top; - info.length = len; - info.align_offset = 0; - info.align_mask = align - 1; - - addr = vm_unmapped_area(&info); - - if (IS_ERR_VALUE(addr)) - return addr; - - err = security_mmap_addr(addr); - return err ? err : addr; -} - -static unsigned long _search_range(struct kgsl_process_private *private, +static unsigned long set_svm_area(struct file *file, struct kgsl_mem_entry *entry, - unsigned long start, unsigned long end, - unsigned long len, uint64_t align) + unsigned long addr, unsigned long len, + unsigned long flags) { - unsigned long cpu, gpu = end, result = -ENOMEM; + struct kgsl_device_private *dev_priv = file->private_data; + struct kgsl_process_private *private = dev_priv->process_priv; + unsigned long ret; - while (gpu > start) { - /* find a new empty spot on the CPU below the last one */ - cpu = _cpu_get_unmapped_area(start, gpu, len, - (unsigned long) align); - if (IS_ERR_VALUE(cpu)) { - result = cpu; - break; - } - /* try to map it on the GPU */ - result = _gpu_set_svm_region(private, entry, cpu, len); - if (!IS_ERR_VALUE(result)) - break; - - trace_kgsl_mem_unmapped_area_collision(entry, cpu, len); - - if (cpu <= start) { - result = -ENOMEM; - break; - } - - /* move downward to the next empty spot on the GPU */ - gpu = _gpu_find_svm(private, start, cpu, len, align); - if (IS_ERR_VALUE(gpu)) { - result = gpu; - break; - } - - /* Check that_gpu_find_svm doesn't put us in a loop */ - if (gpu >= cpu) { - result = -ENOMEM; - break; - } - - /* Break if the recommended GPU address is out of range */ - if (gpu < start) { - result = -ENOMEM; - break; - } - - /* - * Add the length of the chunk to the GPU address to yield the - * upper bound for the CPU search - */ - gpu += len; - } - return result; -} - -static unsigned long _get_svm_area(struct kgsl_process_private *private, - struct kgsl_mem_entry *entry, unsigned long hint, - unsigned long len, unsigned long flags) -{ - uint64_t start, end; - int align_shift = kgsl_memdesc_get_align(&entry->memdesc); - uint64_t align; - unsigned long result; - unsigned long addr; - - if (align_shift >= ilog2(SZ_2M)) - align = SZ_2M; - else if (align_shift >= ilog2(SZ_1M)) - align = SZ_1M; - else if (align_shift >= ilog2(SZ_64K)) - align = SZ_64K; - else - align = SZ_4K; - - align = max_t(uint64_t, align, PAGE_SIZE); - - /* get the GPU pagetable's SVM range */ - if (kgsl_mmu_svm_range(private->pagetable, &start, &end, - entry->memdesc.flags)) - return -ERANGE; - - /* now clamp the range based on the CPU's requirements */ - start = max_t(uint64_t, start, mmap_min_addr); - end = min_t(uint64_t, end, current->mm->mmap_base); - if (start >= end) - return -ERANGE; - - if (flags & MAP_FIXED) { - /* We must honor alignment requirements */ - if (!IS_ALIGNED(hint, align)) - return -EINVAL; - - /* we must use addr 'hint' or fail */ - return _gpu_set_svm_region(private, entry, hint, len); - } else if (hint != 0) { - struct vm_area_struct *vma; - - /* - * See if the hint is usable, if not we will use - * it as the start point for searching. - */ - addr = clamp_t(unsigned long, hint & ~(align - 1), - start, (end - len) & ~(align - 1)); - - vma = find_vma(current->mm, addr); - - if (vma == NULL || ((addr + len) <= vma->vm_start)) { - result = _gpu_set_svm_region(private, entry, addr, len); - - /* On failure drop down to keep searching */ - if (!IS_ERR_VALUE(result)) - return result; - } - } else { - /* no hint, start search at the top and work down */ - addr = end & ~(align - 1); - } + /* Make sure there isn't a vma conflict in the chosen range */ + if (find_vma_intersection(current->mm, addr, addr + len - 1)) + return -ENOMEM; /* - * Search downwards from the hint first. If that fails we - * must try to search above it. + * Do additoinal constraints checking on the address. Passing MAP_FIXED + * ensures that the address we want gets checked */ - result = _search_range(private, entry, start, addr, len, align); - if (IS_ERR_VALUE(result) && hint != 0) - result = _search_range(private, entry, addr, end, len, align); + ret = current->mm->get_unmapped_area(file, addr, len, 0, + flags & MAP_FIXED); - return result; + /* If it passes, attempt to set the region in the SVM */ + if (!IS_ERR_VALUE(ret)) + return _gpu_set_svm_region(private, entry, addr, len); + + return ret; +} + +static unsigned long get_svm_unmapped_area(struct file *file, + struct kgsl_mem_entry *entry, + unsigned long addr, unsigned long len, + unsigned long flags) +{ + struct kgsl_device_private *dev_priv = file->private_data; + struct kgsl_process_private *private = dev_priv->process_priv; + unsigned long align = get_align(entry); + unsigned long ret, iova; + u64 start = 0, end = 0; + + if (flags & MAP_FIXED) { + /* Even fixed addresses need to obey alignment */ + if (!IS_ALIGNED(addr, align)) + return -EINVAL; + + return set_svm_area(file, entry, addr, len, flags); + } + + /* If a hint was provided, try to use that first */ + if (addr) { + if (IS_ALIGNED(addr, align)) { + ret = set_svm_area(file, entry, addr, len, flags); + if (!IS_ERR_VALUE(ret)) + return ret; + } + } + + /* Get the SVM range for the current process */ + if (kgsl_mmu_svm_range(private->pagetable, &start, &end, + entry->memdesc.flags)) + return -ERANGE; + + /* Find the first gap in the iova map */ + iova = kgsl_mmu_find_svm_region(private->pagetable, start, end, + len, align); + + while (!IS_ERR_VALUE(iova)) { + ret = set_svm_area(file, entry, iova, len, flags); + if (!IS_ERR_VALUE(ret)) + return ret; + + iova = kgsl_mmu_find_svm_region(private->pagetable, + start, iova - 1, len, align); + } + + return -ENOMEM; } static unsigned long @@ -4737,28 +4662,26 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, /* Do not allow CPU mappings for secure buffers */ if (kgsl_memdesc_is_secured(&entry->memdesc)) { - val = -EPERM; - goto put; + kgsl_mem_entry_put(entry); + return (unsigned long) -EPERM; } if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - val = get_unmapped_area(NULL, addr, len, 0, flags); + val = current->mm->get_unmapped_area(file, addr, len, 0, flags); if (IS_ERR_VALUE(val)) dev_err_ratelimited(device->dev, "get_unmapped_area: pid %d addr %lx pgoff %lx len %ld failed error %d\n", private->pid, addr, pgoff, len, (int) val); } else { - val = _get_svm_area(private, entry, addr, len, flags); + val = get_svm_unmapped_area(file, entry, addr, len, flags); if (IS_ERR_VALUE(val)) dev_err_ratelimited(device->dev, - "_get_svm_area: pid %d mmap_base %lx addr %lx pgoff %lx len %ld failed error %d\n", - private->pid, - current->mm->mmap_base, addr, - pgoff, len, (int) val); + "_get_svm_area: pid %d addr %lx pgoff %lx len %ld failed error %d\n", + private->pid, addr, pgoff, len, + (int) val); } -put: kgsl_mem_entry_put(entry); return val; } From 2726e792a201881d260921bbb026633ac46c94ae Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:03 -0600 Subject: [PATCH 2/4] msm: kgsl: Fix linked sysfs files kernfs_create_link is an unexported function so we need a workaround. Luckily most of the "linked" sysfs files are our own, so we can just create new attributes with the same callback functions. We're not so lucky with the devfreq nodes but they are optional so we can omit them when we are building as a module. Change-Id: Ic0dedbad7e5f4e28a62ce57abb6451f4865d37ab Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl.c | 2 +- drivers/gpu/msm/kgsl.h | 8 ++++++ drivers/gpu/msm/kgsl_pwrctrl.c | 48 ++++++++++++++++------------------ drivers/gpu/msm/kgsl_pwrctrl.h | 1 - 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 9d3460383830..18767bbdbd12 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -5001,7 +5001,7 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_exit_page_pools(); - kgsl_pwrctrl_uninit_sysfs(device); + kobject_put(device->gpu_sysfs_kobj); idr_destroy(&device->context_idr); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 7b9874a2c3ac..dd4310cd06f3 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -579,6 +579,7 @@ static inline int kgsl_copy_from_user(void *dest, void __user *src, return copy_from_user(dest, src, copy) ? -EFAULT : 0; } +#ifndef MODULE static inline void kgsl_gpu_sysfs_add_link(struct kobject *dst, struct kobject *src, const char *src_name, const char *dst_name) @@ -594,6 +595,13 @@ static inline void kgsl_gpu_sysfs_add_link(struct kobject *dst, kernfs_create_link(dst->sd, dst_name, old); } +#else +static inline void kgsl_gpu_sysfs_add_link(struct kobject *dst, + struct kobject *src, const char *src_name, + const char *dst_name) +{ +} +#endif static inline bool kgsl_is_compat_task(void) { diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 31c367777758..c09d17456f70 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1191,45 +1191,41 @@ static const struct attribute *pwrctrl_attr_list[] = { NULL, }; -struct sysfs_link { - const char *src; - const char *dst; -}; +static DEVICE_ATTR(gpu_busy, 0200, gpu_busy_percentage_show, NULL); +static DEVICE_ATTR(gpu_min_clock, 0644, min_clock_mhz_show, + min_clock_mhz_store); +static DEVICE_ATTR(gpu_max_clock, 0644, max_clock_mhz_show, + max_clock_mhz_store); +static DEVICE_ATTR(gpu_clock, 0200, clock_mhz_show, NULL); +static DEVICE_ATTR(gpu_freq_table, 0200, freq_table_mhz_show, NULL); +static DEVICE_ATTR(gpu_tmu, 0200, temp_show, NULL); -static struct sysfs_link link_names[] = { - { "gpu_model", "gpu_model",}, - { "gpu_busy_percentage", "gpu_busy",}, - { "min_clock_mhz", "gpu_min_clock",}, - { "max_clock_mhz", "gpu_max_clock",}, - { "clock_mhz", "gpu_clock",}, - { "freq_table_mhz", "gpu_freq_table",}, - { "temp", "gpu_tmu",}, +static const struct attribute *pwrctrl_gpu_attr_list[] = { + &dev_attr_gpu_model.attr, + &dev_attr_gpu_busy.attr, + &dev_attr_gpu_min_clock.attr, + &dev_attr_gpu_max_clock.attr, + &dev_attr_gpu_clock.attr, + &dev_attr_gpu_freq_table.attr, + &dev_attr_gpu_tmu.attr, + NULL, }; int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device) { - int i, ret; + int ret; ret = sysfs_create_files(&device->dev->kobj, pwrctrl_attr_list); if (ret) return ret; device->gpu_sysfs_kobj = kobject_create_and_add("gpu", kernel_kobj); - if (IS_ERR_OR_NULL(device->gpu_sysfs_kobj)) - return (device->gpu_sysfs_kobj == NULL) ? - -ENOMEM : PTR_ERR(device->gpu_sysfs_kobj); - for (i = 0; i < ARRAY_SIZE(link_names); i++) - kgsl_gpu_sysfs_add_link(device->gpu_sysfs_kobj, - &device->dev->kobj, link_names[i].src, - link_names[i].dst); + if (!device->gpu_sysfs_kobj) + return 0; - return 0; -} - -void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device) -{ - sysfs_remove_files(&device->dev->kobj, pwrctrl_attr_list); + return sysfs_create_files(device->gpu_sysfs_kobj, + pwrctrl_gpu_attr_list); } /* diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 5b0fe861cad3..659dcb38818a 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -165,7 +165,6 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device, bool on); int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device); -void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device); int kgsl_pwrctrl_change_state(struct kgsl_device *device, int state); int kgsl_clk_set_rate(struct kgsl_device *device, unsigned int pwrlevel); From fef1dd5afc6e6f8107728c861f264d82c87c38ab Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:03 -0600 Subject: [PATCH 3/4] msm: kgsl: Fix context refcounting for adreno debugfs The code is currently using a device ID look up for the context ID. This is presumably because there was a refcounting race when looking at the the debugfs file while the context was being destroyed. Instead of trying to be clever, just take a reference count on the context when the debugfs file is created and release it when the context is detached. This may cause the context to stick around a bit longer, but it sure is cleaner. Change-Id: Ic0dedbad3f30168e74d03eade59218f82b93bee4 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno_debugfs.c | 19 +++++++++++-------- drivers/gpu/msm/adreno_drawctxt.c | 2 ++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index 2af76acb1200..03a59ce24408 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -312,16 +312,14 @@ static int ctx_print(struct seq_file *s, void *unused) static int ctx_open(struct inode *inode, struct file *file) { int ret; - unsigned int id = (unsigned int)(unsigned long)inode->i_private; - struct kgsl_context *context; + struct adreno_context *ctx = inode->i_private; - context = kgsl_context_get(kgsl_get_device(KGSL_DEVICE_3D0), id); - if (context == NULL) + if (!_kgsl_context_get(&ctx->base)) return -ENODEV; - ret = single_open(file, ctx_print, context); + ret = single_open(file, ctx_print, &ctx->base); if (ret) - kgsl_context_put(context); + kgsl_context_put(&ctx->base); return ret; } @@ -350,11 +348,16 @@ adreno_context_debugfs_init(struct adreno_device *adreno_dev, { unsigned char name[16]; + /* + * Get the context here to make sure it still exists for the life of the + * file + */ + _kgsl_context_get(&ctx->base); + snprintf(name, sizeof(name), "%d", ctx->base.id); ctx->debug_root = debugfs_create_file(name, 0444, - adreno_dev->ctx_d_debugfs, - (void *)(unsigned long)ctx->base.id, &ctx_fops); + adreno_dev->ctx_d_debugfs, ctx, &ctx_fops); } void adreno_debugfs_init(struct adreno_device *adreno_dev) diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index 2f7f98db3b8f..ab9ad91bdea4 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -478,6 +478,8 @@ void adreno_drawctxt_detach(struct kgsl_context *context) } debugfs_remove_recursive(drawctxt->debug_root); + /* The debugfs file has a reference, release it */ + kgsl_context_put(context); /* * internal_timestamp is set in adreno_ringbuffer_addcmds, From 032b0de108a37ee198930b881a0f7ff786ea47e1 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 14 Oct 2019 10:41:04 -0600 Subject: [PATCH 4/4] msm: kgsl: Make secure memory depend on QCOM_SECURE_BUFFER Secure memory uses a helper driver to lock memory in the hypervisor. The helper driver is selectable at compile time (CONFIG_QCOM_SECURE_BUFFER) Any attempts to allocate secure memory without the dependent support will return -ENODEV which the kernel and user drivers should know how to handle safely. Change-Id: Ic0dedbadbde75ce8856a677d7c7793cda0c2c727 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/adreno.c | 2 ++ drivers/gpu/msm/kgsl_iommu.c | 41 ++++++++++---------------------- drivers/gpu/msm/kgsl_sharedmem.c | 32 +++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index f01a4be5a886..63dc0e883873 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1427,8 +1427,10 @@ static int adreno_probe(struct platform_device *pdev) * check the GPU capabilities here and modify mmu->secured accordingly */ +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) if (!ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION)) device->mmu.secured = false; +#endif if (ADRENO_FEATURE(adreno_dev, ADRENO_IOCOHERENT)) device->mmu.features |= KGSL_MMU_IO_COHERENT; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index a302f3e0ec97..58c6e62e73b7 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -1003,6 +1003,7 @@ done: return ret; } +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { struct kgsl_device *device = KGSL_MMU_DEVICE(mmu); @@ -1011,7 +1012,6 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; int secure_vmid = VMID_CP_PIXEL; - unsigned int cb_num; if (!mmu->secured) return -EPERM; @@ -1036,23 +1036,17 @@ static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) iommu_set_fault_handler(iommu_pt->domain, kgsl_iommu_fault_handler, pt); - ret = iommu_domain_get_attr(iommu_pt->domain, - DOMAIN_ATTR_CONTEXT_BANK, &cb_num); - if (ret) { - dev_err(device->dev, "get DOMAIN_ATTR_PROCID failed: %d\n", - ret); - goto done; - } - - ctx->cb_num = cb_num; - ctx->regbase = iommu->regbase + KGSL_IOMMU_CB0_OFFSET - + (cb_num << KGSL_IOMMU_CB_SHIFT); - done: if (ret) _free_pt(ctx, pt); return ret; } +#else +static int _init_secure_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) +{ + return -EPERM; +} +#endif static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { @@ -1335,7 +1329,6 @@ static int _setup_secure_context(struct kgsl_mmu *mmu) int ret; struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu); struct kgsl_iommu_context *ctx = &iommu->ctx[KGSL_IOMMU_CONTEXT_SECURE]; - unsigned int cb_num; struct kgsl_iommu_pt *iommu_pt; @@ -1348,22 +1341,12 @@ static int _setup_secure_context(struct kgsl_mmu *mmu) iommu_pt = mmu->securepagetable->priv; ret = _attach_pt(iommu_pt, ctx); - if (ret) - goto done; - - ctx->default_pt = mmu->securepagetable; - - ret = iommu_domain_get_attr(iommu_pt->domain, DOMAIN_ATTR_CONTEXT_BANK, - &cb_num); - if (ret) { - dev_err(KGSL_MMU_DEVICE(mmu)->dev, - "get CONTEXT_BANK attr, err %d\n", ret); - goto done; + if (!ret) { + ctx->default_pt = mmu->securepagetable; + return 0; } - ctx->cb_num = cb_num; -done: - if (ret) - _detach_context(ctx); + + _detach_context(ctx); return ret; } diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index ea39e39b66c1..fa3f7fdb8950 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -8,7 +8,6 @@ #include #include #include -#include #include "kgsl_device.h" #include "kgsl_sharedmem.h" @@ -404,6 +403,10 @@ done: mutex_unlock(&kernel_map_global_lock); } +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) + +#include + static int lock_sgt(struct sg_table *sgt, u64 size) { struct scatterlist *sg; @@ -460,6 +463,7 @@ static int unlock_sgt(struct sg_table *sgt) ClearPagePrivate(sg_page_iter_page(&sg_iter)); return 0; } +#endif static int kgsl_paged_map_kernel(struct kgsl_memdesc *memdesc) { @@ -712,6 +716,7 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) memdesc->ops->free(memdesc); } +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) void kgsl_free_secure_page(struct page *page) { struct sg_table sgt; @@ -758,6 +763,16 @@ struct page *kgsl_alloc_secure_page(void) } return page; } +#else +void kgsl_free_secure_page(struct page *page) +{ +} + +struct page *kgsl_alloc_secure_page(void) +{ + return NULL; +} +#endif int kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, @@ -1029,6 +1044,7 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc) _kgsl_contiguous_free(memdesc); } +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) static void kgsl_free_secure_pool_pages(struct kgsl_memdesc *memdesc) { int ret = unlock_sgt(memdesc->sgt); @@ -1054,6 +1070,7 @@ static void kgsl_free_secure_pool_pages(struct kgsl_memdesc *memdesc) memdesc->sgt = NULL; } +#endif static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc) { @@ -1076,11 +1093,12 @@ static struct kgsl_memdesc_ops kgsl_contiguous_ops = { .vmfault = kgsl_contiguous_vmfault, }; - +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) static struct kgsl_memdesc_ops kgsl_secure_pool_ops = { .free = kgsl_free_secure_pool_pages, /* FIXME: Make sure vmflags / vmfault does the right thing here */ }; +#endif static struct kgsl_memdesc_ops kgsl_pool_ops = { .free = kgsl_free_pool_pages, @@ -1090,6 +1108,7 @@ static struct kgsl_memdesc_ops kgsl_pool_ops = { .unmap_kernel = kgsl_paged_unmap_kernel, }; +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) static int kgsl_alloc_secure_pages(struct kgsl_device *device, struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv) { @@ -1145,6 +1164,7 @@ static int kgsl_alloc_secure_pages(struct kgsl_device *device, return 0; } +#endif static int kgsl_alloc_pages(struct kgsl_device *device, struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv) @@ -1229,11 +1249,19 @@ static int kgsl_alloc_contiguous(struct kgsl_device *device, return ret; } +#if IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) static int kgsl_allocate_secure(struct kgsl_device *device, struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv) { return kgsl_alloc_secure_pages(device, memdesc, size, flags, priv); } +#else +static int kgsl_allocate_secure(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv) +{ + return -ENODEV; +} +#endif int kgsl_allocate_user(struct kgsl_device *device, struct kgsl_memdesc *memdesc, u64 size, u64 flags, u32 priv)