summaryrefslogtreecommitdiff
path: root/drivers/gpu/arm/midgard/mali_kbase_replay.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/arm/midgard/mali_kbase_replay.c')
-rw-r--r--drivers/gpu/arm/midgard/mali_kbase_replay.c232
1 files changed, 106 insertions, 126 deletions
diff --git a/drivers/gpu/arm/midgard/mali_kbase_replay.c b/drivers/gpu/arm/midgard/mali_kbase_replay.c
index d3a3dbfa5241..71f005e32521 100644
--- a/drivers/gpu/arm/midgard/mali_kbase_replay.c
+++ b/drivers/gpu/arm/midgard/mali_kbase_replay.c
@@ -1,6 +1,6 @@
/*
*
- * (C) COPYRIGHT 2014-2016 ARM Limited. All rights reserved.
+ * (C) COPYRIGHT 2014-2015 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
@@ -27,11 +27,15 @@
#include <mali_kbase_mem_linux.h>
#define JOB_NOT_STARTED 0
-#define JOB_TYPE_NULL (1)
-#define JOB_TYPE_VERTEX (5)
-#define JOB_TYPE_TILER (7)
-#define JOB_TYPE_FUSED (8)
-#define JOB_TYPE_FRAGMENT (9)
+#define JOB_TYPE_MASK 0xfe
+#define JOB_TYPE_NULL (1 << 1)
+#define JOB_TYPE_VERTEX (5 << 1)
+#define JOB_TYPE_TILER (7 << 1)
+#define JOB_TYPE_FUSED (8 << 1)
+#define JOB_TYPE_FRAGMENT (9 << 1)
+
+#define JOB_FLAG_DESC_SIZE (1 << 0)
+#define JOB_FLAG_PERFORM_JOB_BARRIER (1 << 8)
#define JOB_HEADER_32_FBD_OFFSET (31*4)
#define JOB_HEADER_64_FBD_OFFSET (44*4)
@@ -54,9 +58,17 @@
#define JOB_SOURCE_ID(status) (((status) >> 16) & 0xFFFF)
#define JOB_POLYGON_LIST (0x03)
-struct fragment_job {
- struct job_descriptor_header header;
-
+struct job_head {
+ u32 status;
+ u32 not_complete_index;
+ u64 fault_addr;
+ u16 flags;
+ u16 index;
+ u16 dependencies[2];
+ union {
+ u64 _64;
+ u32 _32;
+ } next;
u32 x[2];
union {
u64 _64;
@@ -65,43 +77,28 @@ struct fragment_job {
};
static void dump_job_head(struct kbase_context *kctx, char *head_str,
- struct job_descriptor_header *job)
+ struct job_head *job)
{
#ifdef CONFIG_MALI_DEBUG
dev_dbg(kctx->kbdev->dev, "%s\n", head_str);
- dev_dbg(kctx->kbdev->dev,
- "addr = %p\n"
- "exception_status = %x (Source ID: 0x%x Access: 0x%x Exception: 0x%x)\n"
- "first_incomplete_task = %x\n"
- "fault_pointer = %llx\n"
- "job_descriptor_size = %x\n"
- "job_type = %x\n"
- "job_barrier = %x\n"
- "_reserved_01 = %x\n"
- "_reserved_02 = %x\n"
- "_reserved_03 = %x\n"
- "_reserved_04/05 = %x,%x\n"
- "job_index = %x\n"
- "dependencies = %x,%x\n",
- job, job->exception_status,
- JOB_SOURCE_ID(job->exception_status),
- (job->exception_status >> 8) & 0x3,
- job->exception_status & 0xFF,
- job->first_incomplete_task,
- job->fault_pointer, job->job_descriptor_size,
- job->job_type, job->job_barrier, job->_reserved_01,
- job->_reserved_02, job->_reserved_03,
- job->_reserved_04, job->_reserved_05,
- job->job_index,
- job->job_dependency_index_1,
- job->job_dependency_index_2);
-
- if (job->job_descriptor_size)
+ dev_dbg(kctx->kbdev->dev, "addr = %p\n"
+ "status = %x\n"
+ "not_complete_index = %x\n"
+ "fault_addr = %llx\n"
+ "flags = %x\n"
+ "index = %x\n"
+ "dependencies = %x,%x\n",
+ job, job->status, job->not_complete_index,
+ job->fault_addr, job->flags, job->index,
+ job->dependencies[0],
+ job->dependencies[1]);
+
+ if (job->flags & JOB_FLAG_DESC_SIZE)
dev_dbg(kctx->kbdev->dev, "next = %llx\n",
- job->next_job._64);
+ job->next._64);
else
dev_dbg(kctx->kbdev->dev, "next = %x\n",
- job->next_job._32);
+ job->next._32);
#endif
}
@@ -375,81 +372,77 @@ static int kbasep_replay_reset_job(struct kbase_context *kctx,
u32 default_weight, u16 hw_job_id_offset,
bool first_in_chain, bool fragment_chain)
{
- struct fragment_job *frag_job;
- struct job_descriptor_header *job;
+ struct job_head *job;
u64 new_job_header;
struct kbase_vmap_struct map;
- frag_job = kbase_vmap(kctx, *job_header, sizeof(*frag_job), &map);
- if (!frag_job) {
+ job = kbase_vmap(kctx, *job_header, sizeof(*job), &map);
+ if (!job) {
dev_err(kctx->kbdev->dev,
"kbasep_replay_parse_jc: failed to map jc\n");
return -EINVAL;
}
- job = &frag_job->header;
dump_job_head(kctx, "Job header:", job);
- if (job->exception_status == JOB_NOT_STARTED && !fragment_chain) {
+ if (job->status == JOB_NOT_STARTED && !fragment_chain) {
dev_err(kctx->kbdev->dev, "Job already not started\n");
goto out_unmap;
}
- job->exception_status = JOB_NOT_STARTED;
+ job->status = JOB_NOT_STARTED;
- if (job->job_type == JOB_TYPE_VERTEX)
- job->job_type = JOB_TYPE_NULL;
+ if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_VERTEX)
+ job->flags = (job->flags & ~JOB_TYPE_MASK) | JOB_TYPE_NULL;
- if (job->job_type == JOB_TYPE_FUSED) {
+ if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FUSED) {
dev_err(kctx->kbdev->dev, "Fused jobs can not be replayed\n");
goto out_unmap;
}
if (first_in_chain)
- job->job_barrier = 1;
+ job->flags |= JOB_FLAG_PERFORM_JOB_BARRIER;
- if ((job->job_dependency_index_1 + hw_job_id_offset) >
- JOB_HEADER_ID_MAX ||
- (job->job_dependency_index_2 + hw_job_id_offset) >
- JOB_HEADER_ID_MAX ||
- (job->job_index + hw_job_id_offset) > JOB_HEADER_ID_MAX) {
+ if ((job->dependencies[0] + hw_job_id_offset) > JOB_HEADER_ID_MAX ||
+ (job->dependencies[1] + hw_job_id_offset) > JOB_HEADER_ID_MAX ||
+ (job->index + hw_job_id_offset) > JOB_HEADER_ID_MAX) {
dev_err(kctx->kbdev->dev,
"Job indicies/dependencies out of valid range\n");
goto out_unmap;
}
- if (job->job_dependency_index_1)
- job->job_dependency_index_1 += hw_job_id_offset;
- if (job->job_dependency_index_2)
- job->job_dependency_index_2 += hw_job_id_offset;
+ if (job->dependencies[0])
+ job->dependencies[0] += hw_job_id_offset;
+ if (job->dependencies[1])
+ job->dependencies[1] += hw_job_id_offset;
- job->job_index += hw_job_id_offset;
+ job->index += hw_job_id_offset;
- if (job->job_descriptor_size) {
- new_job_header = job->next_job._64;
- if (!job->next_job._64)
- job->next_job._64 = prev_jc;
+ if (job->flags & JOB_FLAG_DESC_SIZE) {
+ new_job_header = job->next._64;
+ if (!job->next._64)
+ job->next._64 = prev_jc;
} else {
- new_job_header = job->next_job._32;
- if (!job->next_job._32)
- job->next_job._32 = prev_jc;
+ new_job_header = job->next._32;
+ if (!job->next._32)
+ job->next._32 = prev_jc;
}
dump_job_head(kctx, "Updated to:", job);
- if (job->job_type == JOB_TYPE_TILER) {
- bool job_64 = job->job_descriptor_size != 0;
+ if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_TILER) {
+ bool job_64 = (job->flags & JOB_FLAG_DESC_SIZE) != 0;
if (kbasep_replay_reset_tiler_job(kctx, *job_header,
tiler_heap_free, hierarchy_mask,
default_weight, job_64) != 0)
goto out_unmap;
- } else if (job->job_type == JOB_TYPE_FRAGMENT) {
+ } else if ((job->flags & JOB_TYPE_MASK) == JOB_TYPE_FRAGMENT) {
u64 fbd_address;
- if (job->job_descriptor_size)
- fbd_address = frag_job->fragment_fbd._64;
+ if (job->flags & JOB_FLAG_DESC_SIZE)
+ fbd_address = job->fragment_fbd._64;
else
- fbd_address = (u64)frag_job->fragment_fbd._32;
+ fbd_address = (u64)job->fragment_fbd._32;
if (fbd_address & FBD_TYPE) {
if (kbasep_replay_reset_mfbd(kctx,
@@ -492,7 +485,7 @@ static int kbasep_replay_find_hw_job_id(struct kbase_context *kctx,
u64 jc, u16 *hw_job_id)
{
while (jc) {
- struct job_descriptor_header *job;
+ struct job_head *job;
struct kbase_vmap_struct map;
dev_dbg(kctx->kbdev->dev,
@@ -505,13 +498,13 @@ static int kbasep_replay_find_hw_job_id(struct kbase_context *kctx,
return -EINVAL;
}
- if (job->job_index > *hw_job_id)
- *hw_job_id = job->job_index;
+ if (job->index > *hw_job_id)
+ *hw_job_id = job->index;
- if (job->job_descriptor_size)
- jc = job->next_job._64;
+ if (job->flags & JOB_FLAG_DESC_SIZE)
+ jc = job->next._64;
else
- jc = job->next_job._32;
+ jc = job->next._32;
kbase_vunmap(kctx, &map);
}
@@ -756,7 +749,7 @@ static int kbasep_replay_parse_payload(struct kbase_context *kctx,
struct base_jd_atom_v2 *t_atom,
struct base_jd_atom_v2 *f_atom)
{
- base_jd_replay_payload *payload = NULL;
+ base_jd_replay_payload *payload;
u64 next;
u64 prev_jc = 0;
u16 hw_job_id_offset = 0;
@@ -767,27 +760,12 @@ static int kbasep_replay_parse_payload(struct kbase_context *kctx,
replay_atom->jc, sizeof(payload));
payload = kbase_vmap(kctx, replay_atom->jc, sizeof(*payload), &map);
+
if (!payload) {
dev_err(kctx->kbdev->dev, "kbasep_replay_parse_payload: failed to map payload into kernel space\n");
return -EINVAL;
}
-#ifdef BASE_LEGACY_UK10_2_SUPPORT
- if (KBASE_API_VERSION(10, 3) > replay_atom->kctx->api_version) {
- base_jd_replay_payload_uk10_2 *payload_uk10_2;
- u16 tiler_core_req;
- u16 fragment_core_req;
-
- payload_uk10_2 = (base_jd_replay_payload_uk10_2 *) payload;
- memcpy(&tiler_core_req, &payload_uk10_2->tiler_core_req,
- sizeof(tiler_core_req));
- memcpy(&fragment_core_req, &payload_uk10_2->fragment_core_req,
- sizeof(fragment_core_req));
- payload->tiler_core_req = (u32)(tiler_core_req & 0x7fff);
- payload->fragment_core_req = (u32)(fragment_core_req & 0x7fff);
- }
-#endif /* BASE_LEGACY_UK10_2_SUPPORT */
-
#ifdef CONFIG_MALI_DEBUG
dev_dbg(kctx->kbdev->dev, "kbasep_replay_parse_payload: payload=%p\n", payload);
dev_dbg(kctx->kbdev->dev, "Payload structure:\n"
@@ -809,35 +787,18 @@ static int kbasep_replay_parse_payload(struct kbase_context *kctx,
payload->fragment_core_req);
payload_dump(kctx, payload);
#endif
+
t_atom->core_req = payload->tiler_core_req | BASEP_JD_REQ_EVENT_NEVER;
f_atom->core_req = payload->fragment_core_req | BASEP_JD_REQ_EVENT_NEVER;
/* Sanity check core requirements*/
- if ((t_atom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_T ||
- (f_atom->core_req & BASE_JD_REQ_ATOM_TYPE) != BASE_JD_REQ_FS ||
+ if ((t_atom->core_req & BASEP_JD_REQ_ATOM_TYPE &
+ ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_T ||
+ (f_atom->core_req & BASEP_JD_REQ_ATOM_TYPE &
+ ~BASE_JD_REQ_COHERENT_GROUP) != BASE_JD_REQ_FS ||
t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES ||
f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES) {
-
- int t_atom_type = t_atom->core_req & BASE_JD_REQ_ATOM_TYPE & ~BASE_JD_REQ_COHERENT_GROUP;
- int f_atom_type = f_atom->core_req & BASE_JD_REQ_ATOM_TYPE & ~BASE_JD_REQ_COHERENT_GROUP & ~BASE_JD_REQ_FS_AFBC;
- int t_has_ex_res = t_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES;
- int f_has_ex_res = f_atom->core_req & BASE_JD_REQ_EXTERNAL_RESOURCES;
-
- if (t_atom_type != BASE_JD_REQ_T) {
- dev_err(kctx->kbdev->dev, "Invalid core requirement: Tiler atom not a tiler job. Was: 0x%x\n Expected: 0x%x",
- t_atom_type, BASE_JD_REQ_T);
- }
- if (f_atom_type != BASE_JD_REQ_FS) {
- dev_err(kctx->kbdev->dev, "Invalid core requirement: Fragment shader atom not a fragment shader. Was 0x%x Expected: 0x%x\n",
- f_atom_type, BASE_JD_REQ_FS);
- }
- if (t_has_ex_res) {
- dev_err(kctx->kbdev->dev, "Invalid core requirement: Tiler atom has external resources.\n");
- }
- if (f_has_ex_res) {
- dev_err(kctx->kbdev->dev, "Invalid core requirement: Fragment shader atom has external resources.\n");
- }
-
+ dev_err(kctx->kbdev->dev, "Invalid core requirements\n");
goto out;
}
@@ -996,7 +957,7 @@ static bool kbase_replay_fault_check(struct kbase_jd_atom *katom)
base_jd_replay_payload *payload;
u64 job_header;
u64 job_loop_detect;
- struct job_descriptor_header *job;
+ struct job_head *job;
struct kbase_vmap_struct job_map;
struct kbase_vmap_struct map;
bool err = false;
@@ -1051,22 +1012,41 @@ static bool kbase_replay_fault_check(struct kbase_jd_atom *katom)
}
- dump_job_head(kctx, "\njob_head structure:\n", job);
+#ifdef CONFIG_MALI_DEBUG
+ dev_dbg(dev, "\njob_head structure:\n"
+ "Source ID:0x%x Access:0x%x Exception:0x%x\n"
+ "at job addr = %p\n"
+ "not_complete_index = 0x%x\n"
+ "fault_addr = 0x%llx\n"
+ "flags = 0x%x\n"
+ "index = 0x%x\n"
+ "dependencies = 0x%x,0x%x\n",
+ JOB_SOURCE_ID(job->status),
+ ((job->status >> 8) & 0x3),
+ (job->status & 0xFF),
+ job,
+ job->not_complete_index,
+ job->fault_addr,
+ job->flags,
+ job->index,
+ job->dependencies[0],
+ job->dependencies[1]);
+#endif
/* Replay only when the polygon list reader caused the
* DATA_INVALID_FAULT */
if ((BASE_JD_EVENT_DATA_INVALID_FAULT == katom->event_code) &&
- (JOB_POLYGON_LIST == JOB_SOURCE_ID(job->exception_status))) {
+ (JOB_POLYGON_LIST == JOB_SOURCE_ID(job->status))) {
err = true;
kbase_vunmap(kctx, &job_map);
break;
}
/* Move on to next fragment job in the list */
- if (job->job_descriptor_size)
- job_header = job->next_job._64;
+ if (job->flags & JOB_FLAG_DESC_SIZE)
+ job_header = job->next._64;
else
- job_header = job->next_job._32;
+ job_header = job->next._32;
kbase_vunmap(kctx, &job_map);