summaryrefslogtreecommitdiff
path: root/mali_kbase/mali_kbase_mem.c
diff options
context:
space:
mode:
authorSiddharth Kapoor <ksiddharth@google.com>2022-03-02 14:51:29 +0800
committerSiddharth Kapoor <ksiddharth@google.com>2022-03-02 14:51:29 +0800
commit88d7d984fed1c2a4358ce2bbc334e82d71e3a391 (patch)
tree18f20402a0ed15ae9fe62b29a9957922ebcc2ada /mali_kbase/mali_kbase_mem.c
parent0207d6c3b7a2002f15c60d08617e956faf5ba90c (diff)
downloadgpu-88d7d984fed1c2a4358ce2bbc334e82d71e3a391.tar.gz
Mali Valhall Android DDK r36p0 KMD
Provenance: 9f72c118d9 (ipdelivery/EAC/v_r36p0) VX504X08X-BU-00000-r36p0-01eac0 - Valhall Android DDK VX504X08X-BU-60000-r36p0-01eac0 - Valhall Android Document Bundle VX504X08X-DC-11001-r36p0-01eac0 - Valhall Android DDK Software Errata VX504X08X-SW-99006-r36p0-01eac0 - Valhall Android Renderscript AOSP parts Signed-off-by: Siddharth Kapoor <ksiddharth@google.com> Change-Id: I4a63b707fedc68d7b7d046596c7098da47a139cb
Diffstat (limited to 'mali_kbase/mali_kbase_mem.c')
-rw-r--r--mali_kbase/mali_kbase_mem.c399
1 files changed, 310 insertions, 89 deletions
diff --git a/mali_kbase/mali_kbase_mem.c b/mali_kbase/mali_kbase_mem.c
index de854f3..625043c 100644
--- a/mali_kbase/mali_kbase_mem.c
+++ b/mali_kbase/mali_kbase_mem.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
/*
*
- * (C) COPYRIGHT 2010-2021 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2010-2022 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
@@ -20,7 +20,7 @@
*/
/**
- * Base kernel memory APIs
+ * DOC: Base kernel memory APIs
*/
#include <linux/dma-buf.h>
#include <linux/kernel.h>
@@ -104,12 +104,24 @@ static struct rb_root *kbase_gpu_va_to_rbtree(struct kbase_context *kctx,
u64 gpu_pfn)
{
struct rb_root *rbtree = NULL;
- struct kbase_reg_zone *exec_va_zone =
- kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_VA);
- /* The gpu_pfn can only be greater than the starting pfn of the EXEC_VA
- * zone if this has been initialized.
- */
+ struct kbase_reg_zone *exec_va_zone = kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_VA);
+
+#if MALI_USE_CSF
+ struct kbase_reg_zone *fixed_va_zone =
+ kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_FIXED_VA);
+
+ struct kbase_reg_zone *exec_fixed_va_zone =
+ kbase_ctx_reg_zone_get(kctx, KBASE_REG_ZONE_EXEC_FIXED_VA);
+
+ if (gpu_pfn >= fixed_va_zone->base_pfn) {
+ rbtree = &kctx->reg_rbtree_fixed;
+ return rbtree;
+ } else if (gpu_pfn >= exec_fixed_va_zone->base_pfn) {
+ rbtree = &kctx->reg_rbtree_exec_fixed;
+ return rbtree;
+ }
+#endif
if (gpu_pfn >= exec_va_zone->base_pfn)
rbtree = &kctx->reg_rbtree_exec;
else {
@@ -350,7 +362,8 @@ static struct kbase_va_region *kbase_region_tracker_find_region_meeting_reqs(
}
/**
- * Remove a region object from the global list.
+ * kbase_remove_va_region - Remove a region object from the global list.
+ *
* @kbdev: The kbase device
* @reg: Region object to remove
*
@@ -478,6 +491,8 @@ KBASE_EXPORT_TEST_API(kbase_remove_va_region);
* @at_reg: The region to replace
* @start_pfn: The Page Frame Number to insert at
* @nr_pages: The number of pages of the region
+ *
+ * Return: 0 on success, error code otherwise.
*/
static int kbase_insert_va_region_nolock(struct kbase_va_region *new_reg,
struct kbase_va_region *at_reg, u64 start_pfn, size_t nr_pages)
@@ -551,6 +566,8 @@ static int kbase_insert_va_region_nolock(struct kbase_va_region *new_reg,
* @addr: the address to insert the region at
* @nr_pages: the number of pages in the region
* @align: the minimum alignment in pages
+ *
+ * Return: 0 on success, error code otherwise.
*/
int kbase_add_va_region(struct kbase_context *kctx,
struct kbase_va_region *reg, u64 addr,
@@ -567,12 +584,19 @@ int kbase_add_va_region(struct kbase_context *kctx,
lockdep_assert_held(&kctx->reg_lock);
- /* The executable allocation from the SAME_VA zone would already have an
+ /* The executable allocation from the SAME_VA zone should already have an
* appropriately aligned GPU VA chosen for it.
- * Also the executable allocation from EXEC_VA zone doesn't need the
- * special alignment.
+ * Also, executable allocations from EXEC_VA don't need the special
+ * alignment.
*/
+#if MALI_USE_CSF
+ /* The same is also true for the EXEC_FIXED_VA zone.
+ */
+#endif
if (!(reg->flags & KBASE_REG_GPU_NX) && !addr &&
+#if MALI_USE_CSF
+ ((reg->flags & KBASE_REG_ZONE_MASK) != KBASE_REG_ZONE_EXEC_FIXED_VA) &&
+#endif
((reg->flags & KBASE_REG_ZONE_MASK) != KBASE_REG_ZONE_EXEC_VA)) {
if (cpu_va_bits > gpu_pc_bits) {
align = max(align, (size_t)((1ULL << gpu_pc_bits)
@@ -604,15 +628,17 @@ KBASE_EXPORT_TEST_API(kbase_add_va_region);
/**
* kbase_add_va_region_rbtree - Insert a region into its corresponding rbtree
*
- * Insert a region into the rbtree that was specified when the region was
- * created. If addr is 0 a free area in the rbtree is used, otherwise the
- * specified address is used.
- *
* @kbdev: The kbase device
* @reg: The region to add
* @addr: The address to add the region at, or 0 to map at any available address
* @nr_pages: The size of the region in pages
* @align: The minimum alignment in pages
+ *
+ * Insert a region into the rbtree that was specified when the region was
+ * created. If addr is 0 a free area in the rbtree is used, otherwise the
+ * specified address is used.
+ *
+ * Return: 0 on success, error code otherwise.
*/
int kbase_add_va_region_rbtree(struct kbase_device *kbdev,
struct kbase_va_region *reg,
@@ -699,6 +725,59 @@ exit:
/*
* @brief Initialize the internal region tracker data structure.
*/
+#if MALI_USE_CSF
+static void kbase_region_tracker_ds_init(struct kbase_context *kctx,
+ struct kbase_va_region *same_va_reg,
+ struct kbase_va_region *custom_va_reg,
+ struct kbase_va_region *exec_va_reg,
+ struct kbase_va_region *exec_fixed_va_reg,
+ struct kbase_va_region *fixed_va_reg)
+{
+ u64 last_zone_end_pfn;
+
+ kctx->reg_rbtree_same = RB_ROOT;
+ kbase_region_tracker_insert(same_va_reg);
+
+ last_zone_end_pfn = same_va_reg->start_pfn + same_va_reg->nr_pages;
+
+ /* Although custom_va_reg doesn't always exist, initialize
+ * unconditionally because of the mem_view debugfs
+ * implementation which relies on it being empty.
+ */
+ kctx->reg_rbtree_custom = RB_ROOT;
+ kctx->reg_rbtree_exec = RB_ROOT;
+
+ if (custom_va_reg) {
+ WARN_ON(custom_va_reg->start_pfn < last_zone_end_pfn);
+ kbase_region_tracker_insert(custom_va_reg);
+ last_zone_end_pfn = custom_va_reg->start_pfn + custom_va_reg->nr_pages;
+ }
+
+ /* Initialize exec, fixed and exec_fixed. These are always
+ * initialized at this stage, if they will exist at all.
+ */
+ kctx->reg_rbtree_fixed = RB_ROOT;
+ kctx->reg_rbtree_exec_fixed = RB_ROOT;
+
+ if (exec_va_reg) {
+ WARN_ON(exec_va_reg->start_pfn < last_zone_end_pfn);
+ kbase_region_tracker_insert(exec_va_reg);
+ last_zone_end_pfn = exec_va_reg->start_pfn + exec_va_reg->nr_pages;
+ }
+
+ if (exec_fixed_va_reg) {
+ WARN_ON(exec_fixed_va_reg->start_pfn < last_zone_end_pfn);
+ kbase_region_tracker_insert(exec_fixed_va_reg);
+ last_zone_end_pfn = exec_fixed_va_reg->start_pfn + exec_fixed_va_reg->nr_pages;
+ }
+
+ if (fixed_va_reg) {
+ WARN_ON(fixed_va_reg->start_pfn < last_zone_end_pfn);
+ kbase_region_tracker_insert(fixed_va_reg);
+ last_zone_end_pfn = fixed_va_reg->start_pfn + fixed_va_reg->nr_pages;
+ }
+}
+#else
static void kbase_region_tracker_ds_init(struct kbase_context *kctx,
struct kbase_va_region *same_va_reg,
struct kbase_va_region *custom_va_reg)
@@ -719,6 +798,7 @@ static void kbase_region_tracker_ds_init(struct kbase_context *kctx,
if (custom_va_reg)
kbase_region_tracker_insert(custom_va_reg);
}
+#endif /* MALI_USE_CSF */
static void kbase_region_tracker_erase_rbtree(struct rb_root *rbtree)
{
@@ -753,6 +833,9 @@ void kbase_region_tracker_term(struct kbase_context *kctx)
kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_exec);
#if MALI_USE_CSF
WARN_ON(!list_empty(&kctx->csf.event_pages_head));
+ kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_exec_fixed);
+ kbase_region_tracker_erase_rbtree(&kctx->reg_rbtree_fixed);
+
#endif
kbase_gpu_vm_unlock(kctx);
}
@@ -764,8 +847,8 @@ void kbase_region_tracker_term_rbtree(struct rb_root *rbtree)
static size_t kbase_get_same_va_bits(struct kbase_context *kctx)
{
- return min(kbase_get_num_cpu_va_bits(kctx),
- (size_t) kctx->kbdev->gpu_props.mmu.va_bits);
+ return min_t(size_t, kbase_get_num_cpu_va_bits(kctx),
+ kctx->kbdev->gpu_props.mmu.va_bits);
}
int kbase_region_tracker_init(struct kbase_context *kctx)
@@ -774,15 +857,38 @@ int kbase_region_tracker_init(struct kbase_context *kctx)
struct kbase_va_region *custom_va_reg = NULL;
size_t same_va_bits = kbase_get_same_va_bits(kctx);
u64 custom_va_size = KBASE_REG_ZONE_CUSTOM_VA_SIZE;
- u64 gpu_va_limit = (1ULL << kctx->kbdev->gpu_props.mmu.va_bits) >> PAGE_SHIFT;
+ u64 gpu_va_bits = kctx->kbdev->gpu_props.mmu.va_bits;
+ u64 gpu_va_limit = (1ULL << gpu_va_bits) >> PAGE_SHIFT;
u64 same_va_pages;
u64 same_va_base = 1u;
int err;
+#if MALI_USE_CSF
+ struct kbase_va_region *exec_va_reg;
+ struct kbase_va_region *exec_fixed_va_reg;
+ struct kbase_va_region *fixed_va_reg;
+
+ u64 exec_va_base;
+ u64 fixed_va_end;
+ u64 exec_fixed_va_base;
+ u64 fixed_va_base;
+ u64 fixed_va_pages;
+#endif
/* Take the lock as kbase_free_alloced_region requires it */
kbase_gpu_vm_lock(kctx);
same_va_pages = (1ULL << (same_va_bits - PAGE_SHIFT)) - same_va_base;
+
+#if MALI_USE_CSF
+ if ((same_va_base + same_va_pages) > KBASE_REG_ZONE_EXEC_VA_BASE_64) {
+ /* Depending on how the kernel is configured, it's possible (eg on aarch64) for
+ * same_va_bits to reach 48 bits. Cap same_va_pages so that the same_va zone
+ * doesn't cross into the exec_va zone.
+ */
+ same_va_pages = KBASE_REG_ZONE_EXEC_VA_BASE_64 - same_va_base;
+ }
+#endif
+
/* all have SAME_VA */
same_va_reg =
kbase_alloc_free_region(&kctx->reg_rbtree_same, same_va_base,
@@ -827,6 +933,69 @@ int kbase_region_tracker_init(struct kbase_context *kctx)
custom_va_size = 0;
}
#endif
+
+#if MALI_USE_CSF
+ /* The position of EXEC_VA depends on whether the client is 32-bit or 64-bit. */
+ exec_va_base = KBASE_REG_ZONE_EXEC_VA_BASE_64;
+
+ /* Similarly the end of the FIXED_VA zone also depends on whether the client
+ * is 32 or 64-bits.
+ */
+ fixed_va_end = KBASE_REG_ZONE_FIXED_VA_END_64;
+
+#if IS_ENABLED(CONFIG_64BIT)
+ if (kbase_ctx_flag(kctx, KCTX_COMPAT)) {
+ exec_va_base = KBASE_REG_ZONE_EXEC_VA_BASE_32;
+ fixed_va_end = KBASE_REG_ZONE_FIXED_VA_END_32;
+ }
+#endif
+
+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_EXEC_VA, exec_va_base,
+ KBASE_REG_ZONE_EXEC_VA_SIZE);
+
+ exec_va_reg = kbase_alloc_free_region(&kctx->reg_rbtree_exec, exec_va_base,
+ KBASE_REG_ZONE_EXEC_VA_SIZE, KBASE_REG_ZONE_EXEC_VA);
+
+ if (!exec_va_reg) {
+ err = -ENOMEM;
+ goto fail_free_custom_va;
+ }
+
+ exec_fixed_va_base = exec_va_base + KBASE_REG_ZONE_EXEC_VA_SIZE;
+
+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_EXEC_FIXED_VA, exec_fixed_va_base,
+ KBASE_REG_ZONE_EXEC_FIXED_VA_SIZE);
+
+ exec_fixed_va_reg =
+ kbase_alloc_free_region(&kctx->reg_rbtree_exec_fixed, exec_fixed_va_base,
+ KBASE_REG_ZONE_EXEC_FIXED_VA_SIZE,
+ KBASE_REG_ZONE_EXEC_FIXED_VA);
+
+ if (!exec_fixed_va_reg) {
+ err = -ENOMEM;
+ goto fail_free_exec_va;
+ }
+
+ fixed_va_base = exec_fixed_va_base + KBASE_REG_ZONE_EXEC_FIXED_VA_SIZE;
+ fixed_va_pages = fixed_va_end - fixed_va_base;
+
+ kbase_ctx_reg_zone_init(kctx, KBASE_REG_ZONE_FIXED_VA, fixed_va_base, fixed_va_pages);
+
+ fixed_va_reg = kbase_alloc_free_region(&kctx->reg_rbtree_fixed, fixed_va_base,
+ fixed_va_pages, KBASE_REG_ZONE_FIXED_VA);
+
+ kctx->gpu_va_end = fixed_va_end;
+
+ if (!fixed_va_reg) {
+ err = -ENOMEM;
+ goto fail_free_exec_fixed_va;
+ }
+
+ kbase_region_tracker_ds_init(kctx, same_va_reg, custom_va_reg, exec_va_reg,
+ exec_fixed_va_reg, fixed_va_reg);
+
+ INIT_LIST_HEAD(&kctx->csf.event_pages_head);
+#else
/* EXEC_VA zone's codepaths are slightly easier when its base_pfn is
* initially U64_MAX
*/
@@ -834,17 +1003,23 @@ int kbase_region_tracker_init(struct kbase_context *kctx)
/* Other zones are 0: kbase_create_context() uses vzalloc */
kbase_region_tracker_ds_init(kctx, same_va_reg, custom_va_reg);
-
kctx->gpu_va_end = same_va_base + same_va_pages + custom_va_size;
- kctx->jit_va = false;
-
-#if MALI_USE_CSF
- INIT_LIST_HEAD(&kctx->csf.event_pages_head);
#endif
+ kctx->jit_va = false;
kbase_gpu_vm_unlock(kctx);
return 0;
+#if MALI_USE_CSF
+fail_free_exec_fixed_va:
+ kbase_free_alloced_region(exec_fixed_va_reg);
+fail_free_exec_va:
+ kbase_free_alloced_region(exec_va_reg);
+fail_free_custom_va:
+ if (custom_va_reg)
+ kbase_free_alloced_region(custom_va_reg);
+#endif
+
fail_free_same_va:
kbase_free_alloced_region(same_va_reg);
fail_unlock:
@@ -874,7 +1049,9 @@ bool kbase_has_exec_va_zone(struct kbase_context *kctx)
}
/**
- * Determine if any allocations have been made on a context's region tracker
+ * kbase_region_tracker_has_allocs - Determine if any allocations have been made
+ * on a context's region tracker
+ *
* @kctx: KBase context
*
* Check the context to determine if any allocations have been made yet from
@@ -1081,6 +1258,7 @@ exit_unlock:
int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages)
{
+#if !MALI_USE_CSF
struct kbase_va_region *exec_va_reg;
struct kbase_reg_zone *exec_va_zone;
struct kbase_reg_zone *target_zone;
@@ -1089,6 +1267,7 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages
unsigned long target_zone_bits;
u64 exec_va_start;
int err;
+#endif
/* The EXEC_VA zone shall be created by making space either:
* - for 64-bit clients, at the end of the process's address space
@@ -1102,6 +1281,12 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages
if (exec_va_pages == 0 || exec_va_pages > KBASE_REG_ZONE_EXEC_VA_MAX_PAGES)
return -EINVAL;
+#if MALI_USE_CSF
+ /* For CSF GPUs we now setup the EXEC_VA zone during initialization,
+ * so this request is a null-op.
+ */
+ return 0;
+#else
kbase_gpu_vm_lock(kctx);
/* Verify that we've not already created a EXEC_VA zone, and that the
@@ -1187,6 +1372,7 @@ int kbase_region_tracker_init_exec(struct kbase_context *kctx, u64 exec_va_pages
exit_unlock:
kbase_gpu_vm_unlock(kctx);
return err;
+#endif /* MALI_USE_CSF */
}
#if MALI_USE_CSF
@@ -1330,7 +1516,8 @@ void kbase_mem_term(struct kbase_device *kbdev)
KBASE_EXPORT_TEST_API(kbase_mem_term);
/**
- * Allocate a free region object.
+ * kbase_alloc_free_region - Allocate a free region object.
+ *
* @rbtree: Backlink to the red-black tree of memory regions.
* @start_pfn: The Page Frame Number in GPU virtual address space.
* @nr_pages: The size of the region in pages.
@@ -1341,6 +1528,7 @@ KBASE_EXPORT_TEST_API(kbase_mem_term);
*
* zone is KBASE_REG_ZONE_CUSTOM_VA or KBASE_REG_ZONE_SAME_VA.
*
+ * Return: pointer to the allocated region object on success, NULL otherwise.
*/
struct kbase_va_region *kbase_alloc_free_region(struct rb_root *rbtree,
u64 start_pfn, size_t nr_pages, int zone)
@@ -1398,6 +1586,14 @@ static struct kbase_context *kbase_reg_flags_to_kctx(
kctx = container_of(rbtree, struct kbase_context,
reg_rbtree_exec);
break;
+#if MALI_USE_CSF
+ case KBASE_REG_ZONE_EXEC_FIXED_VA:
+ kctx = container_of(rbtree, struct kbase_context, reg_rbtree_exec_fixed);
+ break;
+ case KBASE_REG_ZONE_FIXED_VA:
+ kctx = container_of(rbtree, struct kbase_context, reg_rbtree_fixed);
+ break;
+#endif
default:
WARN(1, "Unknown zone in region: flags=0x%lx\n", reg->flags);
break;
@@ -1407,7 +1603,8 @@ static struct kbase_context *kbase_reg_flags_to_kctx(
}
/**
- * Free a region object.
+ * kbase_free_alloced_region - Free a region object.
+ *
* @reg: Region
*
* The described region must be freed of any mapping.
@@ -1629,30 +1826,33 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg)
if (!reg->gpu_alloc)
return -EINVAL;
- /* Tear down down GPU page tables, depending on memory type. */
+ /* Tear down GPU page tables, depending on memory type. */
switch (reg->gpu_alloc->type) {
case KBASE_MEM_TYPE_ALIAS: {
- size_t i = 0;
- struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc;
-
- /* Due to the way the number of valid PTEs and ATEs are tracked
- * currently, only the GPU virtual range that is backed & mapped
- * should be passed to the kbase_mmu_teardown_pages() function,
- * hence individual aliased regions needs to be unmapped
- * separately.
- */
- for (i = 0; i < alloc->imported.alias.nents; i++) {
- if (alloc->imported.alias.aliased[i].alloc) {
- err = kbase_mmu_teardown_pages(
- kctx->kbdev, &kctx->mmu,
- reg->start_pfn +
- (i *
- alloc->imported.alias.stride),
- alloc->imported.alias.aliased[i].length,
- kctx->as_nr);
+ size_t i = 0;
+ struct kbase_mem_phy_alloc *alloc = reg->gpu_alloc;
+
+ /* Due to the way the number of valid PTEs and ATEs are tracked
+ * currently, only the GPU virtual range that is backed & mapped
+ * should be passed to the kbase_mmu_teardown_pages() function,
+ * hence individual aliased regions needs to be unmapped
+ * separately.
+ */
+ for (i = 0; i < alloc->imported.alias.nents; i++) {
+ if (alloc->imported.alias.aliased[i].alloc) {
+ int err_loop = kbase_mmu_teardown_pages(
+ kctx->kbdev, &kctx->mmu,
+ reg->start_pfn +
+ (i *
+ alloc->imported.alias.stride),
+ alloc->imported.alias.aliased[i].length,
+ kctx->as_nr);
+ if (WARN_ON_ONCE(err_loop))
+ err = err_loop;
+ }
}
}
- } break;
+ break;
case KBASE_MEM_TYPE_IMPORTED_UMM:
err = kbase_mmu_teardown_pages(kctx->kbdev, &kctx->mmu,
reg->start_pfn, reg->nr_pages, kctx->as_nr);
@@ -1682,7 +1882,8 @@ int kbase_gpu_munmap(struct kbase_context *kctx, struct kbase_va_region *reg)
/* The allocation could still have active mappings. */
if (user_buf->current_mapping_usage_count == 0) {
kbase_jd_user_buf_unmap(kctx, reg->gpu_alloc,
- (reg->flags & KBASE_REG_GPU_WR));
+ (reg->flags & (KBASE_REG_CPU_WR |
+ KBASE_REG_GPU_WR)));
}
}
}
@@ -2016,22 +2217,35 @@ int kbase_mem_free_region(struct kbase_context *kctx, struct kbase_va_region *re
goto out;
}
+#if MALI_USE_CSF
+ if (((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_FIXED_VA) ||
+ ((reg->flags & KBASE_REG_ZONE_MASK) == KBASE_REG_ZONE_EXEC_FIXED_VA)) {
+ if (reg->flags & KBASE_REG_FIXED_ADDRESS)
+ atomic64_dec(&kctx->num_fixed_allocs);
+ else
+ atomic64_dec(&kctx->num_fixable_allocs);
+ }
+#endif
+
/* This will also free the physical pages */
kbase_free_alloced_region(reg);
- out:
+out:
return err;
}
KBASE_EXPORT_TEST_API(kbase_mem_free_region);
/**
- * Free the region from the GPU and unregister it.
+ * kbase_mem_free - Free the region from the GPU and unregister it.
+ *
* @kctx: KBase context
* @gpu_addr: GPU address to free
*
* This function implements the free operation on a memory segment.
* It will loudly fail if called with outstanding mappings.
+ *
+ * Return: 0 on success.
*/
int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
{
@@ -2043,12 +2257,14 @@ int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
__func__, gpu_addr, (void *)kctx);
if ((gpu_addr & ~PAGE_MASK) && (gpu_addr >= PAGE_SIZE)) {
- dev_warn(kctx->kbdev->dev, "kbase_mem_free: gpu_addr parameter is invalid");
+ dev_warn(kctx->kbdev->dev, "%s: gpu_addr parameter is invalid", __func__);
return -EINVAL;
}
if (gpu_addr == 0) {
- dev_warn(kctx->kbdev->dev, "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using kbase_mem_free\n");
+ dev_warn(kctx->kbdev->dev,
+ "gpu_addr 0 is reserved for the ringbuffer and it's an error to try to free it using %s\n",
+ __func__);
return -EINVAL;
}
kbase_gpu_vm_lock(kctx);
@@ -2074,8 +2290,8 @@ int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
/* Validate the region */
reg = kbase_region_tracker_find_region_base_address(kctx, gpu_addr);
if (kbase_is_region_invalid_or_free(reg)) {
- dev_warn(kctx->kbdev->dev, "kbase_mem_free called with nonexistent gpu_addr 0x%llX",
- gpu_addr);
+ dev_warn(kctx->kbdev->dev, "%s called with nonexistent gpu_addr 0x%llX",
+ __func__, gpu_addr);
err = -EINVAL;
goto out_unlock;
}
@@ -2090,7 +2306,7 @@ int kbase_mem_free(struct kbase_context *kctx, u64 gpu_addr)
err = kbase_mem_free_region(kctx, reg);
}
- out_unlock:
+out_unlock:
kbase_gpu_vm_unlock(kctx);
return err;
}
@@ -2196,6 +2412,11 @@ int kbase_update_region_flags(struct kbase_context *kctx,
if (flags & BASE_MEM_GPU_VA_SAME_4GB_PAGE)
reg->flags |= KBASE_REG_GPU_VA_SAME_4GB_PAGE;
+#if MALI_USE_CSF
+ if (flags & BASE_MEM_FIXED)
+ reg->flags |= KBASE_REG_FIXED_ADDRESS;
+#endif
+
return 0;
}
@@ -3047,6 +3268,14 @@ bool kbase_check_alloc_flags(unsigned long flags)
(BASE_MEM_COHERENT_LOCAL | BASE_MEM_COHERENT_SYSTEM))
return false;
+#if MALI_USE_CSF
+ if ((flags & BASE_MEM_SAME_VA) && (flags & (BASE_MEM_FIXABLE | BASE_MEM_FIXED)))
+ return false;
+
+ if ((flags & BASE_MEM_FIXABLE) && (flags & BASE_MEM_FIXED))
+ return false;
+#endif
+
return true;
}
@@ -3068,7 +3297,11 @@ bool kbase_check_import_flags(unsigned long flags)
if (flags & BASE_MEM_GROW_ON_GPF)
return false;
-#if !MALI_USE_CSF
+#if MALI_USE_CSF
+ /* Imported memory cannot be fixed */
+ if ((flags & (BASE_MEM_FIXED | BASE_MEM_FIXABLE)))
+ return false;
+#else
/* Imported memory cannot be aligned to the end of its initial commit */
if (flags & BASE_MEM_TILER_ALIGN_TOP)
return false;
@@ -3229,7 +3462,7 @@ KBASE_EXPORT_TEST_API(kbase_gpu_vm_unlock);
#if IS_ENABLED(CONFIG_DEBUG_FS)
struct kbase_jit_debugfs_data {
- int (*func)(struct kbase_jit_debugfs_data *);
+ int (*func)(struct kbase_jit_debugfs_data *data);
struct mutex lock;
struct kbase_context *kctx;
u64 active_value;
@@ -3452,8 +3685,8 @@ KBASE_JIT_DEBUGFS_DECLARE(kbase_jit_debugfs_trim_fops,
void kbase_jit_debugfs_init(struct kbase_context *kctx)
{
/* prevent unprivileged use of debug file system
- * in old kernel version
- */
+ * in old kernel version
+ */
#if (KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE)
/* only for newer kernel version debug file system is safe */
const mode_t mode = 0444;
@@ -4236,9 +4469,8 @@ struct kbase_va_region *kbase_jit_allocate(struct kbase_context *kctx,
mutex_unlock(&kctx->jit_evict_lock);
kbase_gpu_vm_unlock(kctx);
- reg = kbase_mem_alloc(kctx, info->va_pages, info->commit_pages,
- info->extension, &flags, &gpu_addr,
- mmu_sync_info);
+ reg = kbase_mem_alloc(kctx, info->va_pages, info->commit_pages, info->extension,
+ &flags, &gpu_addr, mmu_sync_info);
if (!reg) {
/* Most likely not enough GPU virtual space left for
* the new JIT allocation.
@@ -4560,6 +4792,7 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx,
struct mm_struct *mm = alloc->imported.user_buf.mm;
long pinned_pages;
long i;
+ int write;
if (WARN_ON(alloc->type != KBASE_MEM_TYPE_IMPORTED_USER_BUF))
return -EINVAL;
@@ -4574,41 +4807,28 @@ int kbase_jd_user_buf_pin_pages(struct kbase_context *kctx,
if (WARN_ON(reg->gpu_alloc->imported.user_buf.mm != current->mm))
return -EINVAL;
+ write = reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR);
+
#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
+ pinned_pages = get_user_pages(NULL, mm, address, alloc->imported.user_buf.nr_pages,
#if KERNEL_VERSION(4, 4, 168) <= LINUX_VERSION_CODE && \
KERNEL_VERSION(4, 5, 0) > LINUX_VERSION_CODE
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
- pages, NULL);
+ write ? FOLL_WRITE : 0, pages, NULL);
#else
- reg->flags & KBASE_REG_GPU_WR,
- 0, pages, NULL);
+ write, 0, pages, NULL);
#endif
#elif KERNEL_VERSION(4, 9, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR,
- 0, pages, NULL);
+ pinned_pages = get_user_pages_remote(NULL, mm, address, alloc->imported.user_buf.nr_pages,
+ write, 0, pages, NULL);
#elif KERNEL_VERSION(4, 10, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
- pages, NULL);
+ pinned_pages = get_user_pages_remote(NULL, mm, address, alloc->imported.user_buf.nr_pages,
+ write ? FOLL_WRITE : 0, pages, NULL);
#elif KERNEL_VERSION(5, 9, 0) > LINUX_VERSION_CODE
- pinned_pages = get_user_pages_remote(NULL, mm,
- address,
- alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0,
- pages, NULL, NULL);
+ pinned_pages = get_user_pages_remote(NULL, mm, address, alloc->imported.user_buf.nr_pages,
+ write ? FOLL_WRITE : 0, pages, NULL, NULL);
#else
- pinned_pages = pin_user_pages_remote(
- mm, address, alloc->imported.user_buf.nr_pages,
- reg->flags & KBASE_REG_GPU_WR ? FOLL_WRITE : 0, pages, NULL,
- NULL);
+ pinned_pages = pin_user_pages_remote(mm, address, alloc->imported.user_buf.nr_pages,
+ write ? FOLL_WRITE : 0, pages, NULL, NULL);
#endif
if (pinned_pages <= 0)
@@ -4665,7 +4885,8 @@ static int kbase_jd_user_buf_map(struct kbase_context *kctx,
dma_addr = dma_map_page(dev, pages[i],
offset, min,
DMA_BIDIRECTIONAL);
- if (dma_mapping_error(dev, dma_addr))
+ err = dma_mapping_error(dev, dma_addr);
+ if (err)
goto unwind;
alloc->imported.user_buf.dma_addrs[i] = dma_addr;
@@ -4842,7 +5063,7 @@ void kbase_unmap_external_resource(struct kbase_context *kctx,
kbase_reg_current_backed_size(reg),
kctx->as_nr);
- if (reg && ((reg->flags & KBASE_REG_GPU_WR) == 0))
+ if (reg && ((reg->flags & (KBASE_REG_CPU_WR | KBASE_REG_GPU_WR)) == 0))
writeable = false;
kbase_jd_user_buf_unmap(kctx, alloc, writeable);