diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-08-02 03:00:37 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-08-02 03:00:37 +0000 |
commit | 296ac8b24393d95216428aff724eba33e53e7163 (patch) | |
tree | 08c9e60235de3de61d774505158147cd46016f84 | |
parent | 1467bf27534d180bff7c6ea3fc8feea0ad7d4653 (diff) | |
parent | e56f5663a2b589c2cc96ab52c23781d500dfcace (diff) | |
download | gpu-android-gs-pantah-5.10-u-beta5.tar.gz |
Snap for 10566483 from e56f5663a2b589c2cc96ab52c23781d500dfcace to android13-gs-pixel-5.10-releaseandroid-u-beta-5_r0.7android-u-beta-5_r0.5android-u-beta-5_r0.4android-u-beta-5_r0.3android-u-beta-5_r0.2android-u-beta-5_r0.1android-gs-tangorpro-5.10-u-beta5android-gs-raviole-5.10-u-beta5android-gs-pantah-5.10-u-beta5android-gs-lynx-5.10-u-beta5android-gs-felix-5.10-u-beta5android-gs-bluejay-5.10-u-beta5
Change-Id: I9b04523b6c93eece0339a67134d32484f0dd9330
-rw-r--r-- | mali_kbase/csf/mali_kbase_csf.c | 17 | ||||
-rw-r--r-- | mali_kbase/csf/mali_kbase_csf_reset_gpu.c | 5 | ||||
-rw-r--r-- | mali_kbase/mali_kbase_jd.c | 8 | ||||
-rw-r--r-- | mali_kbase/mmu/mali_kbase_mmu.c | 92 | ||||
-rw-r--r-- | mali_kbase/mmu/mali_kbase_mmu_hw.h | 15 | ||||
-rw-r--r-- | mali_kbase/mmu/mali_kbase_mmu_hw_direct.c | 8 |
6 files changed, 139 insertions, 6 deletions
diff --git a/mali_kbase/csf/mali_kbase_csf.c b/mali_kbase/csf/mali_kbase_csf.c index 29542a6..fce6aaa 100644 --- a/mali_kbase/csf/mali_kbase_csf.c +++ b/mali_kbase/csf/mali_kbase_csf.c @@ -852,6 +852,15 @@ void kbase_csf_ring_csg_slots_doorbell(struct kbase_device *kbdev, if (WARN_ON(slot_bitmap > allowed_bitmap)) return; + /* The access to GLB_DB_REQ/ACK needs to be ordered with respect to CSG_REQ/ACK and + * CSG_DB_REQ/ACK to avoid a scenario where a CSI request overlaps with a CSG request + * or 2 CSI requests overlap and FW ends up missing the 2nd request. + * Memory barrier is required, both on Host and FW side, to guarantee the ordering. + * + * 'osh' is used as CPU and GPU would be in the same Outer shareable domain. + */ + dmb(osh); + value = kbase_csf_firmware_global_output(global_iface, GLB_DB_ACK); value ^= slot_bitmap; kbase_csf_firmware_global_input_mask(global_iface, GLB_DB_REQ, value, @@ -890,6 +899,14 @@ void kbase_csf_ring_cs_kernel_doorbell(struct kbase_device *kbdev, WARN_ON(csi_index >= ginfo->stream_num)) return; + /* The access to CSG_DB_REQ/ACK needs to be ordered with respect to + * CS_REQ/ACK to avoid a scenario where CSG_DB_REQ/ACK becomes visible to + * FW before CS_REQ/ACK is set. + * + * 'osh' is used as CPU and GPU would be in the same outer shareable domain. + */ + dmb(osh); + value = kbase_csf_firmware_csg_output(ginfo, CSG_DB_ACK); value ^= (1 << csi_index); kbase_csf_firmware_csg_input_mask(ginfo, CSG_DB_REQ, value, diff --git a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c index ef62c0c..b12a3b4 100644 --- a/mali_kbase/csf/mali_kbase_csf_reset_gpu.c +++ b/mali_kbase/csf/mali_kbase_csf_reset_gpu.c @@ -32,6 +32,8 @@ #include <csf/mali_kbase_csf_firmware_log.h> #include "mali_kbase_config_platform.h" +#include <soc/google/debug-snapshot.h> + enum kbasep_soft_reset_status { RESET_SUCCESS = 0, SOFT_RESET_FAILED, @@ -224,6 +226,9 @@ static void kbase_csf_reset_end_hw_access(struct kbase_device *kbdev, } else { dev_err(kbdev->dev, "Reset failed to complete"); atomic_set(&kbdev->csf.reset.state, KBASE_CSF_RESET_GPU_FAILED); + + /* pixel: This is unrecoverable, collect a ramdump and reboot. */ + dbg_snapshot_emergency_reboot("mali: reset failed - unrecoverable GPU"); } kbase_csf_scheduler_spin_unlock(kbdev, scheduler_spin_lock_flags); diff --git a/mali_kbase/mali_kbase_jd.c b/mali_kbase/mali_kbase_jd.c index 8667819..66064ec 100644 --- a/mali_kbase/mali_kbase_jd.c +++ b/mali_kbase/mali_kbase_jd.c @@ -762,10 +762,13 @@ static void jd_mark_simple_gfx_frame_atoms(struct kbase_jd_atom *katom) } if (dep_fence && dep_vtx) { + unsigned long flags; dev_dbg(kbdev->dev, "Simple gfx frame: {vtx=%pK, wait=%pK}->frag=%pK\n", dep_vtx, dep_fence, katom); + spin_lock_irqsave(&kbdev->hwaccess_lock, flags); katom->atom_flags |= KBASE_KATOM_FLAG_SIMPLE_FRAME_FRAGMENT; dep_vtx->atom_flags |= KBASE_KATOM_FLAG_DEFER_WHILE_POWEROFF; + spin_unlock_irqrestore(&kbdev->hwaccess_lock, flags); } } @@ -839,14 +842,15 @@ bool kbase_jd_done_nolock(struct kbase_jd_atom *katom, bool post_immediately) dev_dbg(kctx->kbdev->dev, "Simple-frame fragment atom %pK unblocked\n", node); - node->atom_flags &= - ~KBASE_KATOM_FLAG_SIMPLE_FRAME_FRAGMENT; for (i = 0; i < 2; i++) { if (node->dep[i].atom && node->dep[i].atom->atom_flags & KBASE_KATOM_FLAG_DEFER_WHILE_POWEROFF) { + unsigned long flags; + spin_lock_irqsave(&kctx->kbdev->hwaccess_lock, flags); node->dep[i].atom->atom_flags &= ~KBASE_KATOM_FLAG_DEFER_WHILE_POWEROFF; + spin_unlock_irqrestore(&kctx->kbdev->hwaccess_lock, flags); dev_dbg(kctx->kbdev->dev, " Undeferred atom %pK\n", node->dep[i].atom); diff --git a/mali_kbase/mmu/mali_kbase_mmu.c b/mali_kbase/mmu/mali_kbase_mmu.c index 2e3c251..8f7b9b5 100644 --- a/mali_kbase/mmu/mali_kbase_mmu.c +++ b/mali_kbase/mmu/mali_kbase_mmu.c @@ -1331,6 +1331,7 @@ page_fault_retry: kbase_gpu_vm_unlock(kctx); } else { int ret = -ENOMEM; + const u8 group_id = region->gpu_alloc->group_id; kbase_gpu_vm_unlock(kctx); @@ -1342,8 +1343,7 @@ page_fault_retry: if (grow_2mb_pool) { /* Round page requirement up to nearest 2 MB */ struct kbase_mem_pool *const lp_mem_pool = - &kctx->mem_pools.large[ - region->gpu_alloc->group_id]; + &kctx->mem_pools.large[group_id]; pages_to_grow = (pages_to_grow + ((1 << lp_mem_pool->order) - 1)) @@ -1353,8 +1353,7 @@ page_fault_retry: } else { #endif struct kbase_mem_pool *const mem_pool = - &kctx->mem_pools.small[ - region->gpu_alloc->group_id]; + &kctx->mem_pools.small[group_id]; ret = kbase_mem_pool_grow(mem_pool, pages_to_grow, kctx->task); #ifdef CONFIG_MALI_2MB_ALLOC @@ -2062,6 +2061,7 @@ int kbase_mmu_insert_pages(struct kbase_device *kbdev, KBASE_EXPORT_TEST_API(kbase_mmu_insert_pages); +#if !MALI_USE_CSF /** * kbase_mmu_flush_noretain() - Flush and invalidate the GPU caches * without retaining the kbase context. @@ -2115,6 +2115,7 @@ static void kbase_mmu_flush_noretain(struct kbase_context *kctx, u64 vpfn, size_ kbase_reset_gpu_locked(kbdev); } } +#endif void kbase_mmu_update(struct kbase_device *kbdev, struct kbase_mmu_table *mmut, @@ -2136,6 +2137,88 @@ void kbase_mmu_disable_as(struct kbase_device *kbdev, int as_nr) kbdev->mmu_mode->disable_as(kbdev, as_nr); } +#if MALI_USE_CSF +void kbase_mmu_disable(struct kbase_context *kctx) +{ + /* Calls to this function are inherently asynchronous, with respect to + * MMU operations. + */ + const enum kbase_caller_mmu_sync_info mmu_sync_info = CALLER_MMU_ASYNC; + struct kbase_device *kbdev = kctx->kbdev; + struct kbase_mmu_hw_op_param op_param = { 0 }; + int lock_err, flush_err; + + /* ASSERT that the context has a valid as_nr, which is only the case + * when it's scheduled in. + * + * as_nr won't change because the caller has the hwaccess_lock + */ + KBASE_DEBUG_ASSERT(kctx->as_nr != KBASEP_AS_NR_INVALID); + + lockdep_assert_held(&kctx->kbdev->hwaccess_lock); + lockdep_assert_held(&kctx->kbdev->mmu_hw_mutex); + + op_param.vpfn = 0; + op_param.nr = ~0; + op_param.op = KBASE_MMU_OP_FLUSH_MEM; + op_param.kctx_id = kctx->id; + op_param.mmu_sync_info = mmu_sync_info; + +#if MALI_USE_CSF + /* 0xF value used to prevent skipping of any levels when flushing */ + if (mmu_flush_cache_on_gpu_ctrl(kbdev)) + op_param.flush_skip_levels = pgd_level_to_skip_flush(0xF); +#endif + + /* lock MMU to prevent existing jobs on GPU from executing while the AS is + * not yet disabled + */ + lock_err = kbase_mmu_hw_do_lock(kbdev, &kbdev->as[kctx->as_nr], &op_param); + if (lock_err) + dev_err(kbdev->dev, "Failed to lock AS %d for ctx %d_%d", kctx->as_nr, kctx->tgid, + kctx->id); + + /* Issue the flush command only when L2 cache is in stable power on state. + * Any other state for L2 cache implies that shader cores are powered off, + * which in turn implies there is no execution happening on the GPU. + */ + if (kbdev->pm.backend.l2_state == KBASE_L2_ON) { + flush_err = kbase_gpu_cache_flush_and_busy_wait(kbdev, + GPU_COMMAND_CACHE_CLN_INV_L2_LSC); + if (flush_err) + dev_err(kbdev->dev, + "Failed to flush GPU cache when disabling AS %d for ctx %d_%d", + kctx->as_nr, kctx->tgid, kctx->id); + } + kbdev->mmu_mode->disable_as(kbdev, kctx->as_nr); + + if (!lock_err) { + /* unlock the MMU to allow it to resume */ + lock_err = + kbase_mmu_hw_do_unlock_no_addr(kbdev, &kbdev->as[kctx->as_nr], &op_param); + if (lock_err) + dev_err(kbdev->dev, "Failed to unlock AS %d for ctx %d_%d", kctx->as_nr, + kctx->tgid, kctx->id); + } + +#if !MALI_USE_CSF + /* + * JM GPUs has some L1 read only caches that need to be invalidated + * with START_FLUSH configuration. Purge the MMU disabled kctx from + * the slot_rb tracking field so such invalidation is performed when + * a new katom is executed on the affected slots. + */ + kbase_backend_slot_kctx_purge_locked(kbdev, kctx); +#endif + + /* kbase_gpu_cache_flush_and_busy_wait() will reset the GPU on timeout. Only + * reset the GPU if locking or unlocking fails. + */ + if (lock_err) + if (kbase_prepare_to_reset_gpu_locked(kbdev, RESET_FLAGS_NONE)) + kbase_reset_gpu_locked(kbdev); +} +#else void kbase_mmu_disable(struct kbase_context *kctx) { /* ASSERT that the context has a valid as_nr, which is only the case @@ -2168,6 +2251,7 @@ void kbase_mmu_disable(struct kbase_context *kctx) kbase_backend_slot_kctx_purge_locked(kctx->kbdev, kctx); #endif } +#endif KBASE_EXPORT_TEST_API(kbase_mmu_disable); static void kbase_mmu_update_and_free_parent_pgds(struct kbase_device *kbdev, diff --git a/mali_kbase/mmu/mali_kbase_mmu_hw.h b/mali_kbase/mmu/mali_kbase_mmu_hw.h index 438dd5e..3291143 100644 --- a/mali_kbase/mmu/mali_kbase_mmu_hw.h +++ b/mali_kbase/mmu/mali_kbase_mmu_hw.h @@ -133,6 +133,21 @@ int kbase_mmu_hw_do_unlock_no_addr(struct kbase_device *kbdev, struct kbase_as * int kbase_mmu_hw_do_unlock(struct kbase_device *kbdev, struct kbase_as *as, const struct kbase_mmu_hw_op_param *op_param); /** + * kbase_mmu_hw_do_lock - Issue a LOCK operation to the MMU. + * + * @kbdev: Kbase device to issue the MMU operation on. + * @as: Address space to issue the MMU operation on. + * @op_param: Pointer to struct containing information about the MMU + * operation to perform. + * + * Context: Acquires the hwaccess_lock, expects the caller to hold the mmu_hw_mutex + * + * Return: Zero if the operation was successful, non-zero otherwise. + */ +int kbase_mmu_hw_do_lock(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param); + +/** * kbase_mmu_hw_do_flush - Issue a flush operation to the MMU. * * @kbdev: Kbase device to issue the MMU operation on. diff --git a/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c b/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c index 1a6157a..122e9ef 100644 --- a/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c +++ b/mali_kbase/mmu/mali_kbase_mmu_hw_direct.c @@ -410,6 +410,14 @@ static int mmu_hw_do_lock(struct kbase_device *kbdev, struct kbase_as *as, return ret; } +int kbase_mmu_hw_do_lock(struct kbase_device *kbdev, struct kbase_as *as, + const struct kbase_mmu_hw_op_param *op_param) +{ + lockdep_assert_held(&kbdev->hwaccess_lock); + + return mmu_hw_do_lock(kbdev, as, op_param); +} + int kbase_mmu_hw_do_unlock_no_addr(struct kbase_device *kbdev, struct kbase_as *as, const struct kbase_mmu_hw_op_param *op_param) { |