summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-02 03:00:37 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-08-02 03:00:37 +0000
commit296ac8b24393d95216428aff724eba33e53e7163 (patch)
tree08c9e60235de3de61d774505158147cd46016f84
parent1467bf27534d180bff7c6ea3fc8feea0ad7d4653 (diff)
parente56f5663a2b589c2cc96ab52c23781d500dfcace (diff)
downloadgpu-android-gs-pantah-5.10-u-beta5.tar.gz
Change-Id: I9b04523b6c93eece0339a67134d32484f0dd9330
-rw-r--r--mali_kbase/csf/mali_kbase_csf.c17
-rw-r--r--mali_kbase/csf/mali_kbase_csf_reset_gpu.c5
-rw-r--r--mali_kbase/mali_kbase_jd.c8
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu.c92
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_hw.h15
-rw-r--r--mali_kbase/mmu/mali_kbase_mmu_hw_direct.c8
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)
{