msm: kgsl: Do not free sharedmem if it cannot be unmapped

If sharedmem cannot be unmapped from the mmu, it can still be accessed
by the GPU. Therefore it is not safe to free the backing memory. In the
case that unmap fails, do not free it or return it to the system.

Change-Id: Iad3e86d043f129a4d71cf862865d9033d4a315e3
Signed-off-by: Lynus Vaz <quic_lvaz@quicinc.com>
This commit is contained in:
Lynus Vaz 2023-11-27 06:53:01 -08:00
parent 8da91b648e
commit 330843f544
2 changed files with 24 additions and 2 deletions

View File

@ -483,6 +483,8 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
size = kgsl_memdesc_footprint(memdesc);
ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
if (ret)
return ret;
atomic_dec(&pagetable->stats.entries);
atomic_long_sub(size, &pagetable->stats.mapped);

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2002,2007-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <asm/cacheflush.h>
@ -948,6 +949,9 @@ static void kgsl_contiguous_free(struct kgsl_memdesc *memdesc)
if (!memdesc->hostptr)
return;
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
return;
atomic_long_sub(memdesc->size, &kgsl_driver.stats.coherent);
#ifdef CONFIG_MM_STAT_UNRECLAIMABLE_PAGES
@ -963,9 +967,14 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
{
int i;
struct scatterlist *sg;
int ret = unlock_sgt(memdesc->sgt);
int ret;
int order = get_order(PAGE_SIZE);
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
return;
ret = unlock_sgt(memdesc->sgt);
if (ret) {
/*
* Unlock of the secure buffer failed. This buffer will
@ -998,7 +1007,12 @@ static void kgsl_free_secure_system_pages(struct kgsl_memdesc *memdesc)
static void kgsl_free_secure_pool_pages(struct kgsl_memdesc *memdesc)
{
int ret = unlock_sgt(memdesc->sgt);
int ret;
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
return;
ret = unlock_sgt(memdesc->sgt);
if (ret) {
/*
@ -1028,6 +1042,9 @@ static void kgsl_free_pool_pages(struct kgsl_memdesc *memdesc)
kgsl_paged_unmap_kernel(memdesc);
WARN_ON(memdesc->hostptr);
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
return;
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
kgsl_pool_free_pages(memdesc->pages, memdesc->page_count);
@ -1045,6 +1062,9 @@ static void kgsl_free_system_pages(struct kgsl_memdesc *memdesc)
kgsl_paged_unmap_kernel(memdesc);
WARN_ON(memdesc->hostptr);
if (memdesc->priv & KGSL_MEMDESC_MAPPED)
return;
atomic_long_sub(memdesc->size, &kgsl_driver.stats.page_alloc);
for (i = 0; i < memdesc->page_count; i++) {