diff options
Diffstat (limited to 'dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c')
-rw-r--r-- | dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c | 167 |
1 files changed, 88 insertions, 79 deletions
diff --git a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c index cbb0c76..bee3513 100644 --- a/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c +++ b/dvalin/kernel/drivers/gpu/arm/midgard/mali_kbase_softjobs.c @@ -1,11 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2011-2020 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2011-2021 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 * Foundation, and any use by you of this program is subject to the terms - * of such GNU licence. + * of such GNU license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -16,12 +17,8 @@ * along with this program; if not, you can access it online at * http://www.gnu.org/licenses/gpl-2.0.html. * - * SPDX-License-Identifier: GPL-2.0 - * */ - - #include <mali_kbase.h> #include <linux/dma-buf.h> @@ -30,8 +27,9 @@ #include <mali_kbase_sync.h> #endif #include <linux/dma-mapping.h> -#include <mali_base_kernel.h> +#include <uapi/gpu/arm/midgard/mali_base_kernel.h> #include <mali_kbase_hwaccess_time.h> +#include <mali_kbase_kinstr_jm.h> #include <mali_kbase_mem_linux.h> #include <tl/mali_kbase_tracepoints.h> #include <mali_linux_trace.h> @@ -42,10 +40,9 @@ #include <linux/kernel.h> #include <linux/cache.h> +#if !MALI_USE_CSF /** - * @file mali_kbase_softjobs.c - * - * This file implements the logic behind software only jobs that are + * DOC: This file implements the logic behind software only jobs that are * executed within the driver rather than being handed over to the GPU. */ @@ -136,7 +133,7 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) void *user_result; struct timespec64 ts; struct base_dump_cpu_gpu_counters data; - u64 system_time; + u64 system_time = 0ULL; u64 cycle_counter; u64 jc = katom->jc; struct kbase_context *kctx = katom->kctx; @@ -146,7 +143,11 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) /* Take the PM active reference as late as possible - otherwise, it could * delay suspend until we process the atom (which may be at the end of a - * long chain of dependencies */ + * long chain of dependencies + */ +#ifdef CONFIG_MALI_ARBITER_SUPPORT + atomic_inc(&kctx->kbdev->pm.gpu_users_waiting); +#endif /* CONFIG_MALI_ARBITER_SUPPORT */ pm_active_err = kbase_pm_context_active_handle_suspend(kctx->kbdev, KBASE_PM_SUSPEND_HANDLER_DONT_REACTIVATE); if (pm_active_err) { struct kbasep_js_device_data *js_devdata = &kctx->kbdev->js_data; @@ -164,6 +165,10 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) return pm_active_err; } +#ifdef CONFIG_MALI_ARBITER_SUPPORT + else + atomic_dec(&kctx->kbdev->pm.gpu_users_waiting); +#endif /* CONFIG_MALI_ARBITER_SUPPORT */ kbase_backend_get_gpu_time(kctx->kbdev, &cycle_counter, &system_time, &ts); @@ -181,7 +186,8 @@ static int kbase_dump_cpu_gpu_time(struct kbase_jd_atom *katom) /* GPU_WR access is checked on the range for returning the result to * userspace for the following reasons: * - security, this is currently how imported user bufs are checked. - * - userspace ddk guaranteed to assume region was mapped as GPU_WR */ + * - userspace ddk guaranteed to assume region was mapped as GPU_WR + */ user_result = kbase_vmap_prot(kctx, jc, sizeof(data), KBASE_REG_GPU_WR, &map); if (!user_result) return 0; @@ -292,7 +298,7 @@ static void kbase_fence_debug_check_atom(struct kbase_jd_atom *katom) if (!kbase_sync_fence_in_info_get(dep, &info)) { dev_warn(dev, - "\tVictim trigger atom %d fence [%p] %s: %s\n", + "\tVictim trigger atom %d fence [%pK] %s: %s\n", kbase_jd_atom_id(kctx, dep), info.fence, info.name, @@ -321,11 +327,11 @@ static void kbase_fence_debug_wait_timeout(struct kbase_jd_atom *katom) return; } - dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%p] after %dms\n", + dev_warn(dev, "ctx %d_%d: Atom %d still waiting for fence [%pK] after %dms\n", kctx->tgid, kctx->id, kbase_jd_atom_id(kctx, katom), info.fence, timeout_ms); - dev_warn(dev, "\tGuilty fence [%p] %s: %s\n", + dev_warn(dev, "\tGuilty fence [%pK] %s: %s\n", info.fence, info.name, kbase_sync_status_string(info.status)); @@ -713,14 +719,16 @@ out_unlock: out_cleanup: /* Frees allocated memory for kbase_debug_copy_job struct, including - * members, and sets jc to 0 */ + * members, and sets jc to 0 + */ kbase_debug_copy_finish(katom); kfree(user_buffers); return ret; } +#endif /* !MALI_USE_CSF */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE static void *dma_buf_kmap_page(struct kbase_mem_phy_alloc *gpu_alloc, unsigned long page_num, struct page **page) { @@ -801,16 +809,16 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx, dma_to_copy = min(dma_buf->size, (size_t)(buf_data->nr_extres_pages * PAGE_SIZE)); ret = dma_buf_begin_cpu_access(dma_buf, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS) - 0, dma_to_copy, +#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) + 0, dma_to_copy, #endif - DMA_FROM_DEVICE); + DMA_FROM_DEVICE); if (ret) goto out_unlock; for (i = 0; i < dma_to_copy/PAGE_SIZE && target_page_nr < buf_data->nr_pages; i++) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE struct page *pg; void *extres_page = dma_buf_kmap_page(gpu_alloc, i, &pg); #else @@ -822,20 +830,20 @@ int kbase_mem_copy_from_extres(struct kbase_context *kctx, buf_data->nr_pages, &target_page_nr, offset); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0) +#if KERNEL_VERSION(5, 6, 0) <= LINUX_VERSION_CODE kunmap(pg); #else dma_buf_kunmap(dma_buf, i, extres_page); #endif if (ret) - goto out_unlock; + break; } } dma_buf_end_cpu_access(dma_buf, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0) && !defined(CONFIG_CHROMEOS) - 0, dma_to_copy, +#if KERNEL_VERSION(4, 6, 0) > LINUX_VERSION_CODE && !defined(CONFIG_CHROMEOS) + 0, dma_to_copy, #endif - DMA_FROM_DEVICE); + DMA_FROM_DEVICE); break; } default: @@ -846,6 +854,7 @@ out_unlock: return ret; } +#if !MALI_USE_CSF static int kbase_debug_copy(struct kbase_jd_atom *katom) { struct kbase_debug_copy_buffer *buffers = katom->softjob_data; @@ -863,6 +872,7 @@ static int kbase_debug_copy(struct kbase_jd_atom *katom) return 0; } +#endif /* !MALI_USE_CSF */ #define KBASEP_JIT_ALLOC_GPU_ADDR_ALIGNMENT ((u32)0x7) @@ -899,7 +909,7 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx, if (info->flags & ~(BASE_JIT_ALLOC_VALID_FLAGS)) return -EINVAL; -#if !MALI_JIT_PRESSURE_LIMIT +#if !MALI_JIT_PRESSURE_LIMIT_BASE /* If just-in-time memory allocation pressure limit feature is disabled, * heap_info_gpu_addr must be zeroed-out */ @@ -907,21 +917,19 @@ int kbasep_jit_alloc_validate(struct kbase_context *kctx, return -EINVAL; #endif +#if !MALI_USE_CSF /* If BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE is set, heap_info_gpu_addr * cannot be 0 */ if ((info->flags & BASE_JIT_ALLOC_HEAP_INFO_IS_SIZE) && !info->heap_info_gpu_addr) return -EINVAL; +#endif /* !MALI_USE_CSF */ return 0; } - -#if (KERNEL_VERSION(3, 18, 63) > LINUX_VERSION_CODE) -#define offsetofend(TYPE, MEMBER) \ - (offsetof(TYPE, MEMBER) + sizeof(((TYPE *)0)->MEMBER)) -#endif +#if !MALI_USE_CSF /* * Sizes of user data to copy for each just-in-time memory interface version @@ -998,10 +1006,10 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) ret = kbasep_jit_alloc_validate(kctx, info); if (ret) goto free_info; - KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITALLOCINFO(kbdev, katom, - info->va_pages, info->commit_pages, info->extent, - info->id, info->bin_id, info->max_allocations, - info->flags, info->usage_id); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_JITALLOCINFO( + kbdev, katom, info->va_pages, info->commit_pages, + info->extension, info->id, info->bin_id, + info->max_allocations, info->flags, info->usage_id); } katom->jit_blocked = false; @@ -1016,7 +1024,7 @@ static int kbase_jit_allocate_prepare(struct kbase_jd_atom *katom) * though the region is valid it doesn't represent the * same thing it used to. * - * Complete validation of va_pages, commit_pages and extent + * Complete validation of va_pages, commit_pages and extension * isn't done here as it will be done during the call to * kbase_mem_alloc. */ @@ -1091,14 +1099,19 @@ static int kbase_jit_allocate_process(struct kbase_jd_atom *katom) } } -#if MALI_JIT_PRESSURE_LIMIT - /** - * If this is the only JIT_ALLOC atom in-flight then allow it to exceed - * the defined pressure limit. +#if MALI_JIT_PRESSURE_LIMIT_BASE + /* + * If this is the only JIT_ALLOC atom in-flight or if JIT pressure limit + * is disabled at the context scope, then bypass JIT pressure limit + * logic in kbase_jit_allocate(). */ - if (kctx->jit_current_allocations == 0) + if (!kbase_ctx_flag(kctx, KCTX_JPL_ENABLED) + || (kctx->jit_current_allocations == 0)) { ignore_pressure_limit = true; -#endif /* MALI_JIT_PRESSURE_LIMIT */ + } +#else + ignore_pressure_limit = true; +#endif /* MALI_JIT_PRESSURE_LIMIT_BASE */ for (i = 0, info = katom->softjob_data; i < count; i++, info++) { if (kctx->jit_alloc[info->id]) { @@ -1215,10 +1228,10 @@ static int kbase_jit_allocate_process(struct kbase_jd_atom *katom) MIDGARD_MMU_BOTTOMLEVEL, kctx->jit_group_id); #endif - KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT(kbdev, katom, - info->gpu_alloc_addr, new_addr, info->flags, - entry_mmu_flags, info->id, info->commit_pages, - info->extent, info->va_pages); + KBASE_TLSTREAM_TL_ATTRIB_ATOM_JIT( + kbdev, katom, info->gpu_alloc_addr, new_addr, + info->flags, entry_mmu_flags, info->id, + info->commit_pages, info->extension, info->va_pages); kbase_vunmap(kctx, &mapping); kbase_trace_jit_report_gpu_mem(kctx, reg, @@ -1358,12 +1371,16 @@ void kbase_jit_retry_pending_alloc(struct kbase_context *kctx) list_for_each_safe(i, tmp, &jit_pending_alloc_list) { struct kbase_jd_atom *pending_atom = list_entry(i, struct kbase_jd_atom, queue); + KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kctx->kbdev, pending_atom); + kbase_kinstr_jm_atom_sw_start(pending_atom); if (kbase_jit_allocate_process(pending_atom) == 0) { /* Atom has completed */ INIT_WORK(&pending_atom->work, kbasep_jit_finish_worker); queue_work(kctx->jctx.job_done_wq, &pending_atom->work); } + KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kctx->kbdev, pending_atom); + kbase_kinstr_jm_atom_sw_stop(pending_atom); } } @@ -1412,41 +1429,27 @@ static int kbase_ext_res_prepare(struct kbase_jd_atom *katom) struct base_external_resource_list *ext_res; u64 count = 0; size_t copy_size; - int ret; user_ext_res = (__user struct base_external_resource_list *) (uintptr_t) katom->jc; /* Fail the job if there is no info structure */ - if (!user_ext_res) { - ret = -EINVAL; - goto fail; - } + if (!user_ext_res) + return -EINVAL; - if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0) { - ret = -EINVAL; - goto fail; - } + if (copy_from_user(&count, &user_ext_res->count, sizeof(u64)) != 0) + return -EINVAL; /* Is the number of external resources in range? */ - if (!count || count > BASE_EXT_RES_COUNT_MAX) { - ret = -EINVAL; - goto fail; - } + if (!count || count > BASE_EXT_RES_COUNT_MAX) + return -EINVAL; /* Copy the information for safe access and future storage */ copy_size = sizeof(*ext_res); copy_size += sizeof(struct base_external_resource) * (count - 1); - ext_res = kzalloc(copy_size, GFP_KERNEL); - if (!ext_res) { - ret = -ENOMEM; - goto fail; - } - - if (copy_from_user(ext_res, user_ext_res, copy_size) != 0) { - ret = -EINVAL; - goto free_info; - } + ext_res = memdup_user(user_ext_res, copy_size); + if (IS_ERR(ext_res)) + return PTR_ERR(ext_res); /* * Overwrite the count with the first value incase it was changed @@ -1457,11 +1460,6 @@ static int kbase_ext_res_prepare(struct kbase_jd_atom *katom) katom->softjob_data = ext_res; return 0; - -free_info: - kfree(ext_res); -fail: - return ret; } static void kbase_ext_res_process(struct kbase_jd_atom *katom, bool map) @@ -1538,6 +1536,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom) struct kbase_device *kbdev = kctx->kbdev; KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_START(kbdev, katom); + kbase_kinstr_jm_atom_sw_start(katom); trace_sysgraph(SGR_SUBMIT, kctx->id, kbase_jd_atom_id(kctx, katom)); @@ -1600,6 +1599,7 @@ int kbase_process_soft_job(struct kbase_jd_atom *katom) /* Atom is complete */ KBASE_TLSTREAM_TL_EVENT_ATOM_SOFTJOB_END(kbdev, katom); + kbase_kinstr_jm_atom_sw_stop(katom); return ret; } @@ -1635,7 +1635,9 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) struct base_fence fence; int fd; - if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + if (copy_from_user(&fence, + (__user void *)(uintptr_t)katom->jc, + sizeof(fence)) != 0) return -EINVAL; fd = kbase_sync_fence_out_create(katom, @@ -1644,7 +1646,8 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) return -EINVAL; fence.basep.fd = fd; - if (0 != copy_to_user((__user void *)(uintptr_t) katom->jc, &fence, sizeof(fence))) { + if (copy_to_user((__user void *)(uintptr_t)katom->jc, + &fence, sizeof(fence)) != 0) { kbase_sync_fence_out_remove(katom); kbase_sync_fence_close_fd(fd); fence.basep.fd = -EINVAL; @@ -1657,7 +1660,9 @@ int kbase_prepare_soft_job(struct kbase_jd_atom *katom) struct base_fence fence; int ret; - if (0 != copy_from_user(&fence, (__user void *)(uintptr_t) katom->jc, sizeof(fence))) + if (copy_from_user(&fence, + (__user void *)(uintptr_t)katom->jc, + sizeof(fence)) != 0) return -EINVAL; /* Get a reference to the fence object */ @@ -1776,6 +1781,9 @@ void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) if (kbase_process_soft_job(katom_iter) == 0) { kbase_finish_soft_job(katom_iter); resched |= jd_done_nolock(katom_iter, NULL); +#ifdef CONFIG_MALI_ARBITER_SUPPORT + atomic_dec(&kbdev->pm.gpu_users_waiting); +#endif /* CONFIG_MALI_ARBITER_SUPPORT */ } mutex_unlock(&kctx->jctx.lock); } @@ -1783,3 +1791,4 @@ void kbase_resume_suspended_soft_jobs(struct kbase_device *kbdev) if (resched) kbase_js_sched_all(kbdev); } +#endif /* !MALI_USE_CSF */ |