diff options
author | qctecmdr <qctecmdr@localhost> | 2023-02-25 12:23:52 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2023-02-25 12:23:52 -0800 |
commit | a631d6f2b4419c58a40c5fa2665220c198559a81 (patch) | |
tree | a803759a0c7472b71a135300629265dd7f175836 | |
parent | 50706341635081263ac3a28739c34670b2d500c2 (diff) | |
parent | 03f9b6046176cb890e352b9d409dd8ac1d2f769a (diff) | |
download | graphics-a631d6f2b4419c58a40c5fa2665220c198559a81.tar.gz |
Merge "msm: kgsl: Add support to handle hardware fence timeout"
-rw-r--r-- | adreno_gen7_hwsched_hfi.c | 293 | ||||
-rw-r--r-- | adreno_hfi.h | 54 | ||||
-rw-r--r-- | adreno_hwsched.c | 77 | ||||
-rw-r--r-- | adreno_hwsched.h | 10 | ||||
-rw-r--r-- | adreno_trace.h | 68 |
5 files changed, 482 insertions, 20 deletions
diff --git a/adreno_gen7_hwsched_hfi.c b/adreno_gen7_hwsched_hfi.c index 0cfe3e7..d2e8e0e 100644 --- a/adreno_gen7_hwsched_hfi.c +++ b/adreno_gen7_hwsched_hfi.c @@ -254,6 +254,93 @@ static u32 get_payload_rb_key_legacy(struct adreno_device *adreno_dev, return 0; } +struct syncobj_flags { + unsigned long mask; + const char *name; +}; + +static void _get_syncobj_string(char *str, u32 max_size, struct hfi_syncobj *syncobj, u32 index) +{ + u32 count = scnprintf(str, max_size, "syncobj[%d] ctxt_id:%lu seqno:%lu flags:", index, + syncobj->ctxt_id, syncobj->seq_no); + u32 i; + bool first = true; + static const struct syncobj_flags _flags[] = { + GMU_SYNCOBJ_FLAGS, { -1, NULL }}; + + for (i = 0; _flags[i].name; i++) { + if (!(syncobj->flags & _flags[i].mask)) + continue; + + if (first) { + count += scnprintf(str + count, max_size - count, "%s", _flags[i].name); + first = false; + } else { + count += scnprintf(str + count, max_size - count, "|%s", _flags[i].name); + } + } +} + +static void log_syncobj(struct gen7_gmu_device *gmu, struct hfi_submit_syncobj *cmd) +{ + struct hfi_syncobj *syncobj = (struct hfi_syncobj *)&cmd[1]; + char str[128]; + u32 i = 0; + + for (i = 0; i < cmd->num_syncobj; i++) { + _get_syncobj_string(str, sizeof(str), syncobj, i); + dev_err(&gmu->pdev->dev, "%s\n", str); + syncobj++; + } +} + +static void find_timeout_syncobj(struct adreno_device *adreno_dev, u32 ctxt_id, u32 ts) +{ + struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev); + struct kgsl_context *context = NULL; + struct adreno_context *drawctxt; + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + struct gmu_context_queue_header *hdr; + struct hfi_submit_syncobj *cmd; + u32 *queue, i; + int ret; + + /* We want to get the context even if it is detached */ + read_lock(&device->context_lock); + context = idr_find(&device->context_idr, ctxt_id); + ret = _kgsl_context_get(context); + read_unlock(&device->context_lock); + + if (!ret) + return; + + drawctxt = ADRENO_CONTEXT(context); + + hdr = drawctxt->gmu_context_queue.hostptr; + queue = (u32 *)(drawctxt->gmu_context_queue.hostptr + sizeof(*hdr)); + + for (i = hdr->read_index; i != hdr->write_index;) { + if (MSG_HDR_GET_ID(queue[i]) != H2F_MSG_ISSUE_SYNCOBJ) { + i = (i + MSG_HDR_GET_SIZE(queue[i])) % hdr->queue_size; + continue; + } + + cmd = (struct hfi_submit_syncobj *)&queue[i]; + + if (cmd->timestamp == ts) { + log_syncobj(gmu, cmd); + break; + } + i = (i + MSG_HDR_GET_SIZE(queue[i])) % hdr->queue_size; + } + + if (i == hdr->write_index) + dev_err(&gmu->pdev->dev, "Couldn't find unsignaled syncobj ctx:%d ts:%d\n", + ctxt_id, ts); + + kgsl_context_put(context); +} + static void log_gpu_fault_legacy(struct adreno_device *adreno_dev) { struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev); @@ -382,6 +469,11 @@ static void log_gpu_fault_legacy(struct adreno_device *adreno_dev) case GMU_GPU_AQE1_ILLEGAL_INST_ERROR: dev_crit_ratelimited(dev, "AQE1 Illegal instruction error\n"); break; + case GMU_SYNCOBJ_TIMEOUT_ERROR: + dev_crit_ratelimited(dev, "syncobj timeout ctx %d ts %u\n", + cmd->ctxt_id, cmd->ts); + find_timeout_syncobj(adreno_dev, cmd->ctxt_id, cmd->ts); + break; case GMU_CP_UNKNOWN_ERROR: fallthrough; default: @@ -610,6 +702,11 @@ static void log_gpu_fault(struct adreno_device *adreno_dev) case GMU_GPU_AQE1_ILLEGAL_INST_ERROR: dev_crit_ratelimited(dev, "AQE1 Illegal instruction error\n"); break; + case GMU_SYNCOBJ_TIMEOUT_ERROR: + dev_crit_ratelimited(dev, "syncobj timeout ctx %d ts %u\n", + cmd->gc.ctxt_id, cmd->gc.ts); + find_timeout_syncobj(adreno_dev, cmd->gc.ctxt_id, cmd->gc.ts); + break; case GMU_CP_UNKNOWN_ERROR: fallthrough; default: @@ -649,6 +746,191 @@ static void process_ctx_bad(struct adreno_device *adreno_dev) adreno_hwsched_fault(adreno_dev, ADRENO_HARD_FAULT); } +#define GET_QUERIED_FENCE_INDEX(x) (x / BITS_PER_SYNCOBJ_QUERY) +#define GET_QUERIED_FENCE_BIT(x) (x % BITS_PER_SYNCOBJ_QUERY) + +static bool fence_is_queried(struct hfi_syncobj_query_cmd *cmd, u32 fence_index) +{ + u32 index = GET_QUERIED_FENCE_INDEX(fence_index); + u32 bit = GET_QUERIED_FENCE_BIT(fence_index); + + return (cmd->queries[index].query_bitmask & BIT(bit)); +} + +static void set_fence_signal_bit(struct adreno_device *adreno_dev, + struct hfi_syncobj_query_cmd *reply, struct dma_fence *fence, u32 fence_index, + char *name) +{ + u32 index = GET_QUERIED_FENCE_INDEX(fence_index); + u32 bit = GET_QUERIED_FENCE_BIT(fence_index); + struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev); + u64 flags = ADRENO_HW_FENCE_SW_STATUS_PENDING; + char value[32] = "unknown"; + + if (fence->ops->timeline_value_str) + fence->ops->timeline_value_str(fence, value, sizeof(value)); + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + dev_err(&gmu->pdev->dev, + "GMU is waiting for signaled fence(ctx:%ld seqno:%ld value:%s)\n", + fence->context, fence->seqno, value); + reply->queries[index].query_bitmask |= BIT(bit); + flags = ADRENO_HW_FENCE_SW_STATUS_SIGNALED; + } + trace_adreno_hw_fence_query(fence->context, fence->seqno, flags, name, value); +} + +static void gen7_syncobj_query_reply(struct adreno_device *adreno_dev, + struct kgsl_drawobj *drawobj, struct hfi_syncobj_query_cmd *cmd) +{ + struct hfi_syncobj_query_cmd reply = {0}; + struct gen7_hfi *hfi = to_gen7_hfi(adreno_dev); + int i, j, fence_index = 0; + struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); + const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + + for (i = 0; i < syncobj->numsyncs; i++) { + struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i]; + struct kgsl_sync_fence_cb *kcb = event->handle; + struct dma_fence **fences; + struct dma_fence_array *array; + struct event_fence_info *info = event->priv; + u32 num_fences; + + array = to_dma_fence_array(kcb->fence); + if (array != NULL) { + num_fences = array->num_fences; + fences = array->fences; + } else { + num_fences = 1; + fences = &kcb->fence; + } + + for (j = 0; j < num_fences; j++, fence_index++) { + if (!fence_is_queried(cmd, fence_index)) + continue; + + set_fence_signal_bit(adreno_dev, &reply, fences[j], fence_index, + info ? info->fences[j].name : "unknown"); + } + } + + reply.hdr = CREATE_MSG_HDR(F2H_MSG_SYNCOBJ_QUERY, sizeof(reply), + HFI_MSG_CMD); + reply.hdr = MSG_HDR_SET_SEQNUM(reply.hdr, + atomic_inc_return(&hfi->seqnum)); + reply.gmu_ctxt_id = cmd->gmu_ctxt_id; + reply.sync_obj_ts = cmd->sync_obj_ts; + + trace_adreno_syncobj_query_reply(reply.gmu_ctxt_id, reply.sync_obj_ts, + gpudev->read_alwayson(adreno_dev)); + + gen7_hfi_send_cmd_async(adreno_dev, &reply); +} + +struct syncobj_query_work { + /** @cmd: The query command to be processed */ + struct hfi_syncobj_query_cmd cmd; + /** @context: kgsl context that is waiting for this sync object */ + struct kgsl_context *context; + /** @work: The work structure to execute syncobj query reply */ + struct kthread_work work; +}; + +static void gen7_process_syncobj_query_work(struct kthread_work *work) +{ + struct syncobj_query_work *query_work = container_of(work, + struct syncobj_query_work, work); + struct hfi_syncobj_query_cmd *cmd = (struct hfi_syncobj_query_cmd *)&query_work->cmd; + struct kgsl_context *context = query_work->context; + struct kgsl_device *device = context->device; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_hwsched *hwsched = &adreno_dev->hwsched; + struct cmd_list_obj *obj; + bool missing = true; + + mutex_lock(&hwsched->mutex); + mutex_lock(&device->mutex); + + list_for_each_entry(obj, &hwsched->cmd_list, node) { + struct kgsl_drawobj *drawobj = obj->drawobj; + + if ((drawobj->type & SYNCOBJ_TYPE) == 0) + continue; + + if ((drawobj->context->id == cmd->gmu_ctxt_id) && + (drawobj->timestamp == cmd->sync_obj_ts)) { + gen7_syncobj_query_reply(adreno_dev, drawobj, cmd); + missing = false; + break; + } + } + + if (missing) { + struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev); + struct adreno_context *drawctxt = ADRENO_CONTEXT(context); + struct gmu_context_queue_header *hdr = drawctxt->gmu_context_queue.hostptr; + + /* + * If the sync object is not found, it can only mean that the sync object was + * retired by the GMU in the meanwhile. However, if that is not the case, then + * we have a problem. + */ + if (timestamp_cmp(cmd->sync_obj_ts, hdr->sync_obj_ts) > 0) { + dev_err(&gmu->pdev->dev, "Missing sync object ctx:%d ts:%d retired:%d\n", + context->id, cmd->sync_obj_ts, hdr->sync_obj_ts); + gmu_core_fault_snapshot(device); + adreno_hwsched_fault(adreno_dev, ADRENO_HARD_FAULT); + } + } + + mutex_unlock(&device->mutex); + mutex_unlock(&hwsched->mutex); + + kgsl_context_put(context); + kfree(query_work); +} + +static void gen7_trigger_syncobj_query(struct adreno_device *adreno_dev, + u32 *rcvd) +{ + struct syncobj_query_work *query_work; + struct adreno_hwsched *hwsched = &adreno_dev->hwsched; + struct hfi_syncobj_query_cmd *cmd = (struct hfi_syncobj_query_cmd *)rcvd; + struct kgsl_context *context = NULL; + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + const struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev); + int ret; + + trace_adreno_syncobj_query(cmd->gmu_ctxt_id, cmd->sync_obj_ts, + gpudev->read_alwayson(adreno_dev)); + + /* + * We need the context even if it is detached. Hence, we can't use kgsl_context_get here. + * We must make sure that this context id doesn't get destroyed (to avoid re-use) until GMU + * has ack'd the query reply. + */ + read_lock(&device->context_lock); + context = idr_find(&device->context_idr, cmd->gmu_ctxt_id); + ret = _kgsl_context_get(context); + read_unlock(&device->context_lock); + + if (!ret) + return; + + query_work = kzalloc(sizeof(*query_work), GFP_KERNEL); + if (!query_work) { + kgsl_context_put(context); + return; + } + + kthread_init_work(&query_work->work, gen7_process_syncobj_query_work); + memcpy(&query_work->cmd, cmd, sizeof(*cmd)); + query_work->context = context; + + kthread_queue_work(hwsched->worker, &query_work->work); +} + static void gen7_hwsched_process_msgq(struct adreno_device *adreno_dev) { struct gen7_gmu_device *gmu = to_gen7_gmu(adreno_dev); @@ -683,6 +965,8 @@ static void gen7_hwsched_process_msgq(struct adreno_device *adreno_dev) } else if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_TS_RETIRE) { log_profiling_info(adreno_dev, rcvd); adreno_hwsched_trigger(adreno_dev); + } else if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_SYNCOBJ_QUERY) { + gen7_trigger_syncobj_query(adreno_dev, rcvd); } else if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_GMU_CNTR_RELEASE) { struct hfi_gmu_cntr_release_cmd *cmd = (struct hfi_gmu_cntr_release_cmd *) rcvd; @@ -2188,12 +2472,12 @@ static void populate_kgsl_fence(struct hfi_syncobj *obj, struct kgsl_sync_timeline *ktimeline = kfence->parent; unsigned long flags; - obj->flags |= GMU_SYNCOBJ_KGSL_FENCE; + obj->flags |= BIT(GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT); spin_lock_irqsave(&ktimeline->lock, flags); /* This means that the context is going away. Mark the fence as triggered */ if (!ktimeline->context) { - obj->flags |= GMU_SYNCOBJ_RETIRED; + obj->flags |= BIT(GMU_SYNCOBJ_FLAG_SIGNALED_BIT); spin_unlock_irqrestore(&ktimeline->lock, flags); return; } @@ -2258,8 +2542,9 @@ static int _submit_hw_fence(struct adreno_device *adreno_dev, return ret; } - if (test_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags)) - obj->flags |= GMU_SYNCOBJ_RETIRED; + if (test_bit(MSM_HW_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags) || + test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags)) + obj->flags |= BIT(GMU_SYNCOBJ_FLAG_SIGNALED_BIT); obj->ctxt_id = fences[j]->context; obj->seq_no = fences[j]->seqno; diff --git a/adreno_hfi.h b/adreno_hfi.h index 437f842..46d7311 100644 --- a/adreno_hfi.h +++ b/adreno_hfi.h @@ -453,6 +453,7 @@ struct hfi_queue_table { #define F2H_MSG_CONTEXT_BAD 150 #define H2F_MSG_HW_FENCE_INFO 151 #define H2F_MSG_ISSUE_SYNCOBJ 152 +#define F2H_MSG_SYNCOBJ_QUERY 153 enum gmu_ret_type { GMU_SUCCESS = 0, @@ -759,9 +760,22 @@ struct hfi_ts_notify_cmd { /* This indicates that the SYNCOBJ is kgsl output fence */ -#define GMU_SYNCOBJ_KGSL_FENCE BIT(0) -/* This indicates that the SYNCOBJ is already retired */ -#define GMU_SYNCOBJ_RETIRED BIT(1) +#define GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT 0 +/* This indicates that the SYNCOBJ is signaled */ +#define GMU_SYNCOBJ_FLAG_SIGNALED_BIT 1 +/* This indicates that the SYNCOBJ's software status is queried */ +#define GMU_SYNCOBJ_FLAG_QUERY_SW_STATUS_BIT 2 +/* This indicates that the SYNCOBJ's software status is signaled */ +#define GMU_SYNCOBJ_FLAG_SW_STATUS_SIGNALED_BIT 3 +/* This indicates that the SYNCOBJ's software status is pending */ +#define GMU_SYNCOBJ_FLAG_SW_STATUS_PENDING_BIT 4 + +#define GMU_SYNCOBJ_FLAGS \ + { BIT(GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT), "KGSL"}, \ + { BIT(GMU_SYNCOBJ_FLAG_SIGNALED_BIT), "SIGNALED"}, \ + { BIT(GMU_SYNCOBJ_FLAG_QUERY_SW_STATUS_BIT), "QUERIED"}, \ + { BIT(GMU_SYNCOBJ_FLAG_SW_STATUS_SIGNALED_BIT), "SW_SIGNALED"}, \ + { BIT(GMU_SYNCOBJ_FLAG_SW_STATUS_PENDING_BIT), "SW_PENDING"} /* F2H */ struct hfi_ts_retire_cmd { @@ -883,6 +897,37 @@ struct hfi_hw_fence_info { u64 hash_index; } __packed; +/* The software fence corresponding to the queried hardware fence has not signaled */ +#define ADRENO_HW_FENCE_SW_STATUS_PENDING BIT(0) +/* The software fence corresponding to the queried hardware fence has signaled */ +#define ADRENO_HW_FENCE_SW_STATUS_SIGNALED BIT(1) + +struct hfi_syncobj_query { + /** + * @query_bitmask: Bitmask representing the sync object descriptors to be queried. For + * example, to query the second sync object descriptor(index=1) in a sync object, + * bit(1) should be set in this bitmask. + */ + u32 query_bitmask; +} __packed; + +#define MAX_SYNCOBJ_QUERY_BITS 128 +#define BITS_PER_SYNCOBJ_QUERY 32 +#define MAX_SYNCOBJ_QUERY_DWORDS (MAX_SYNCOBJ_QUERY_BITS / BITS_PER_SYNCOBJ_QUERY) + +struct hfi_syncobj_query_cmd { + /** @hdr: Header for the fence info packet */ + u32 hdr; + /** @version: Version of the fence info packet */ + u32 version; + /** @gmu_ctxt_id: GMU Context id to which this SYNC object belongs */ + u32 gmu_ctxt_id; + /** @sync_obj_ts: Timestamp of this SYNC object */ + u32 sync_obj_ts; + /** @queries: Array of query bitmasks */ + struct hfi_syncobj_query queries[MAX_SYNCOBJ_QUERY_DWORDS]; +} __packed; + /** * struct pending_cmd - data structure to track outstanding HFI * command messages @@ -1022,7 +1067,8 @@ struct payload_section { #define GMU_GPU_AQE1_UCODE_ERROR 627 #define GMU_GPU_AQE1_HW_FAULT_ERROR 628 #define GMU_GPU_AQE1_ILLEGAL_INST_ERROR 629 - +/* GMU encountered a sync object which is signaled via software but not via hardware */ +#define GMU_SYNCOBJ_TIMEOUT_ERROR 630 /* GPU encountered an unknown CP error */ #define GMU_CP_UNKNOWN_ERROR 700 diff --git a/adreno_hwsched.c b/adreno_hwsched.c index 6497ed4..a03f2db 100644 --- a/adreno_hwsched.c +++ b/adreno_hwsched.c @@ -5,6 +5,7 @@ */ #include <dt-bindings/soc/qcom,ipcc.h> +#include <linux/dma-fence-array.h> #include <linux/soc/qcom/msm_hw_fence.h> #include <soc/qcom/msm_performance.h> @@ -16,14 +17,6 @@ #include "kgsl_timeline.h" #include <linux/msm_kgsl.h> -/* This structure represents inflight command object */ -struct cmd_list_obj { - /** @drawobj: Handle to the draw object */ - struct kgsl_drawobj *drawobj; - /** @node: List node to put it in the list of inflight commands */ - struct list_head node; -}; - /* * Number of commands that can be queued in a context before it sleeps * @@ -1707,6 +1700,62 @@ static bool context_is_throttled(struct kgsl_device *device, return false; } +static void _print_syncobj(struct adreno_device *adreno_dev, struct kgsl_drawobj *drawobj) +{ + int i, j, fence_index = 0; + struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj); + struct kgsl_device *device = KGSL_DEVICE(adreno_dev); + + for (i = 0; i < syncobj->numsyncs; i++) { + struct kgsl_drawobj_sync_event *event = &syncobj->synclist[i]; + struct kgsl_sync_fence_cb *kcb = event->handle; + struct dma_fence **fences; + struct dma_fence_array *array; + u32 num_fences; + + array = to_dma_fence_array(kcb->fence); + if (array != NULL) { + num_fences = array->num_fences; + fences = array->fences; + } else { + num_fences = 1; + fences = &kcb->fence; + } + + for (j = 0; j < num_fences; j++, fence_index++) { + bool kgsl = is_kgsl_fence(fences[j]); + bool signaled = test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fences[j]->flags); + char value[32] = "unknown"; + + if (fences[j]->ops->timeline_value_str) + fences[j]->ops->timeline_value_str(fences[j], value, sizeof(value)); + + dev_err(device->dev, + "dma fence[%d] signaled:%d kgsl:%d ctx:%lu seqno:%lu value:%s\n", + fence_index, signaled, kgsl, fences[j]->context, fences[j]->seqno, + value); + } + } + +} + +static void print_fault_syncobj(struct adreno_device *adreno_dev, + u32 ctxt_id, u32 ts) +{ + struct adreno_hwsched *hwsched = &adreno_dev->hwsched; + struct cmd_list_obj *obj; + + list_for_each_entry(obj, &hwsched->cmd_list, node) { + struct kgsl_drawobj *drawobj = obj->drawobj; + + if (drawobj->type == SYNCOBJ_TYPE) { + if ((ctxt_id == drawobj->context->id) && + (ts == drawobj->timestamp)) + _print_syncobj(adreno_dev, drawobj); + } + } +} + static void adreno_hwsched_reset_and_snapshot_legacy(struct adreno_device *adreno_dev, int fault) { struct kgsl_drawobj *drawobj = NULL; @@ -1723,6 +1772,12 @@ static void adreno_hwsched_reset_and_snapshot_legacy(struct adreno_device *adren if (hwsched->recurring_cmdobj) srcu_notifier_call_chain(&device->nh, GPU_SSR_BEGIN, NULL); + if (cmd->error == GMU_SYNCOBJ_TIMEOUT_ERROR) { + print_fault_syncobj(adreno_dev, cmd->ctxt_id, cmd->ts); + kgsl_device_snapshot(device, NULL, NULL, true); + goto done; + } + /* * First, try to see if the faulted command object is marked * in case there was a context bad hfi. But, with stall-on-fault, @@ -1795,6 +1850,12 @@ static void adreno_hwsched_reset_and_snapshot(struct adreno_device *adreno_dev, if (hwsched->recurring_cmdobj) srcu_notifier_call_chain(&device->nh, GPU_SSR_BEGIN, NULL); + if (cmd->error == GMU_SYNCOBJ_TIMEOUT_ERROR) { + print_fault_syncobj(adreno_dev, cmd->gc.ctxt_id, cmd->gc.ts); + kgsl_device_snapshot(device, NULL, NULL, true); + goto done; + } + /* * First, try to see if the faulted command object is marked * in case there was a context bad hfi. But, with stall-on-fault, diff --git a/adreno_hwsched.h b/adreno_hwsched.h index c9bb3d0..962f044 100644 --- a/adreno_hwsched.h +++ b/adreno_hwsched.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _ADRENO_HWSCHED_H_ @@ -11,6 +11,14 @@ #include "kgsl_sync.h" +/* This structure represents inflight command object */ +struct cmd_list_obj { + /** @drawobj: Handle to the draw object */ + struct kgsl_drawobj *drawobj; + /** @node: List node to put it in the list of inflight commands */ + struct list_head node; +}; + /** * struct adreno_hw_fence_entry - A structure to store hardware fence and the context */ diff --git a/adreno_trace.h b/adreno_trace.h index ff91810..8e7c355 100644 --- a/adreno_trace.h +++ b/adreno_trace.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #if !defined(_ADRENO_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) @@ -56,6 +56,33 @@ TRACE_EVENT(adreno_cmdbatch_queued, ) ); +TRACE_EVENT(adreno_hw_fence_query, + TP_PROTO(u64 context, u64 seqno, u32 flags, const char *name, const char *val), + TP_ARGS(context, seqno, flags, name, val), + TP_STRUCT__entry( + __field(u64, context) + __field(u64, seqno) + __field(u32, flags) + __string(fence_name, name) + __string(val, val) + ), + TP_fast_assign( + __entry->context = context; + __entry->seqno = seqno; + __entry->flags = flags; + __assign_str(fence_name, name); + __assign_str(val, val); + ), + TP_printk( + "id=%lld seqno=%lld sw_status=%s name=%s val=%s", + __entry->context, __entry->seqno, + __entry->flags ? __print_flags(__entry->flags, "|", + { ADRENO_HW_FENCE_SW_STATUS_PENDING, "PENDING" }, + { ADRENO_HW_FENCE_SW_STATUS_SIGNALED, "SIGNALED" }) : "none", + __get_str(fence_name), + __get_str(val)) +); + TRACE_EVENT(adreno_input_hw_fence, TP_PROTO(u32 id, u64 context, u64 seqno, u64 flags, const char *name), TP_ARGS(id, context, seqno, flags, name), @@ -77,11 +104,46 @@ TRACE_EVENT(adreno_input_hw_fence, "ctx=%u id=%lld seqno=%lld flags=%s name=%s", __entry->id, __entry->context, __entry->seqno, __entry->flags ? __print_flags(__entry->flags, "|", - { GMU_SYNCOBJ_KGSL_FENCE, "KGSL_FENCE" }, - { GMU_SYNCOBJ_RETIRED, "RETIRED" }) : "none", + GMU_SYNCOBJ_FLAGS) : "none", __get_str(fence_name)) ); +TRACE_EVENT(adreno_syncobj_query_reply, + TP_PROTO(u32 id, u32 timestamp, uint64_t ticks), + TP_ARGS(id, timestamp, ticks), + TP_STRUCT__entry( + __field(u32, id) + __field(u32, timestamp) + __field(uint64_t, ticks) + ), + TP_fast_assign( + __entry->id = id; + __entry->timestamp = timestamp; + __entry->ticks = ticks; + ), + TP_printk( + "ctx=%u ts=%u ticks=%lld", + __entry->id, __entry->timestamp, __entry->ticks) +); + +TRACE_EVENT(adreno_syncobj_query, + TP_PROTO(u32 id, u32 timestamp, uint64_t ticks), + TP_ARGS(id, timestamp, ticks), + TP_STRUCT__entry( + __field(u32, id) + __field(u32, timestamp) + __field(uint64_t, ticks) + ), + TP_fast_assign( + __entry->id = id; + __entry->timestamp = timestamp; + __entry->ticks = ticks; + ), + TP_printk( + "ctx=%u ts=%u ticks=%lld", + __entry->id, __entry->timestamp, __entry->ticks) +); + TRACE_EVENT(adreno_syncobj_submitted, TP_PROTO(u32 id, u32 timestamp, u32 num_syncobj, uint64_t ticks), |