From b912747ec749bdae7fa96651c686a8ccbc75e20a Mon Sep 17 00:00:00 2001 From: Sushmita Susheelendra Date: Tue, 15 Sep 2020 22:58:34 -0600 Subject: [PATCH] msm: kgsl: Add support for GMU log streaming The GMU streams events to the host by sending an HFI message on the f2h debug queue. These messages will be processed by by the f2h daemon. The HFI interrupt handler will add these packets to a secondary list, not the primary list into which the more time critical TS_RETIRE and other messages go. The f2h daemon first processes packets on the main list and then the ones on the secondary list to avoid delaying the time critical packets. It then reads the events from the GMU log in memory and writes them out to ftrace. Change-Id: I3f6cc13f39c2a60d24f2b92c4a97bacef8036f85 Signed-off-by: Sushmita Susheelendra --- drivers/gpu/msm/adreno_a6xx_hfi.c | 12 ++-- drivers/gpu/msm/adreno_a6xx_hfi.h | 8 +++ drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c | 74 ++++++++++++++++++++++- drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h | 2 + drivers/gpu/msm/adreno_trace.h | 21 +++++++ 5 files changed, 108 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/msm/adreno_a6xx_hfi.c b/drivers/gpu/msm/adreno_a6xx_hfi.c index 49f8d1d35d10..f0dd27cf3f81 100644 --- a/drivers/gpu/msm/adreno_a6xx_hfi.c +++ b/drivers/gpu/msm/adreno_a6xx_hfi.c @@ -473,7 +473,7 @@ static int a6xx_hfi_send_test(struct adreno_device *adreno_dev) return a6xx_hfi_send_generic_req(adreno_dev, &cmd); } -static void receive_err_req(struct a6xx_gmu_device *gmu, void *rcvd) +void adreno_a6xx_receive_err_req(struct a6xx_gmu_device *gmu, void *rcvd) { struct hfi_err_cmd *cmd = rcvd; @@ -483,7 +483,7 @@ static void receive_err_req(struct a6xx_gmu_device *gmu, void *rcvd) (char *) cmd->data); } -static void receive_debug_req(struct a6xx_gmu_device *gmu, void *rcvd) +void adreno_a6xx_receive_debug_req(struct a6xx_gmu_device *gmu, void *rcvd) { struct hfi_debug_cmd *cmd = rcvd; @@ -503,10 +503,10 @@ static void a6xx_hfi_v1_receiver(struct a6xx_gmu_device *gmu, uint32_t *rcvd, /* V1 Request Handler */ switch (MSG_HDR_GET_ID(rcvd[0])) { case F2H_MSG_ERR: /* No Reply */ - receive_err_req(gmu, rcvd); + adreno_a6xx_receive_err_req(gmu, rcvd); break; case F2H_MSG_DEBUG: /* No Reply */ - receive_debug_req(gmu, rcvd); + adreno_a6xx_receive_debug_req(gmu, rcvd); break; default: /* No Reply */ dev_err(&gmu->pdev->dev, @@ -540,10 +540,10 @@ int a6xx_hfi_process_queue(struct a6xx_gmu_device *gmu, /* V2 Request Handler */ switch (MSG_HDR_GET_ID(rcvd[0])) { case F2H_MSG_ERR: /* No Reply */ - receive_err_req(gmu, rcvd); + adreno_a6xx_receive_err_req(gmu, rcvd); break; case F2H_MSG_DEBUG: /* No Reply */ - receive_debug_req(gmu, rcvd); + adreno_a6xx_receive_debug_req(gmu, rcvd); break; default: /* No Reply */ dev_err(&gmu->pdev->dev, diff --git a/drivers/gpu/msm/adreno_a6xx_hfi.h b/drivers/gpu/msm/adreno_a6xx_hfi.h index 70314b922270..f43efe6e1d6c 100644 --- a/drivers/gpu/msm/adreno_a6xx_hfi.h +++ b/drivers/gpu/msm/adreno_a6xx_hfi.h @@ -534,6 +534,12 @@ struct hfi_submit_cmd { u32 numibs; } __packed; +struct hfi_log_block { + u32 hdr; + u32 version; + u32 start_index; + u32 stop_index; +} __packed; /** * struct pending_cmd - data structure to track outstanding HFI @@ -717,4 +723,6 @@ int a6xx_hfi_process_queue(struct a6xx_gmu_device *gmu, * Return: 0 on success or negative error on failure */ int a6xx_hfi_cmdq_write(struct adreno_device *adreno_dev, u32 *msg); +void adreno_a6xx_receive_err_req(struct a6xx_gmu_device *gmu, void *rcvd); +void adreno_a6xx_receive_debug_req(struct a6xx_gmu_device *gmu, void *rcvd); #endif diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c index bb90c9178aa5..e91b2fe93d4a 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c @@ -222,6 +222,45 @@ static void process_msgq_irq(struct adreno_device *adreno_dev) } } +static void adreno_a6xx_add_log_block(struct adreno_device *adreno_dev, u32 *msg) +{ + struct f2h_packet *pkt = kmem_cache_alloc(f2h_cache, GFP_ATOMIC); + struct a6xx_hwsched_hfi *hfi = to_a6xx_hwsched_hfi(adreno_dev); + u32 size = MSG_HDR_GET_SIZE(msg[0]) << 2; + + if (!pkt) + return; + + memcpy(pkt->rcvd, msg, min_t(u32, size, sizeof(pkt->rcvd))); + + /* + * Add the log block packets from GMU to a secondary list to ensure + * the time critical TS_RETIRE packet processing on the primary list + * is not delayed + */ + llist_add(&pkt->node, &hfi->f2h_secondary_list); + + wake_up_interruptible(&hfi->f2h_wq); +} + +static void process_dbgq_irq(struct adreno_device *adreno_dev) +{ + struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); + u32 rcvd[MAX_RCVD_SIZE]; + + while (a6xx_hfi_queue_read(gmu, HFI_DBG_ID, rcvd, sizeof(rcvd)) > 0) { + + if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_ERR) + adreno_a6xx_receive_err_req(gmu, rcvd); + + if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_DEBUG) + adreno_a6xx_receive_debug_req(gmu, rcvd); + + if (MSG_HDR_GET_ID(rcvd[0]) == F2H_MSG_LOG_BLOCK) + adreno_a6xx_add_log_block(adreno_dev, rcvd); + } +} + /* HFI interrupt handler */ static irqreturn_t a6xx_hwsched_hfi_handler(int irq, void *data) { @@ -245,7 +284,7 @@ static irqreturn_t a6xx_hwsched_hfi_handler(int irq, void *data) if (status & HFI_IRQ_MSGQ_MASK) process_msgq_irq(adreno_dev); if (status & HFI_IRQ_DBGQ_MASK) - a6xx_hfi_process_queue(gmu, HFI_DBG_ID, NULL); + process_dbgq_irq(adreno_dev); if (status & HFI_IRQ_CM3_FAULT_MASK) { atomic_set(&gmu->cm3_fault, 1); @@ -840,6 +879,24 @@ static void process_ctx_bad(struct adreno_device *adreno_dev, void *rcvd) adreno_hwsched_mark_drawobj(adreno_dev, cmd->ctxt_id, cmd->ts); } +static void process_log_block(struct adreno_device *adreno_dev, void *data) +{ + struct a6xx_gmu_device *gmu = to_a6xx_gmu(adreno_dev); + struct hfi_log_block *cmd = data; + u32 *log_event = gmu->gmu_log->hostptr; + u32 start, end; + + start = cmd->start_index; + end = cmd->stop_index; + + log_event += start * 4; + while (start != end) { + trace_gmu_event(log_event); + log_event += 4; + start++; + } +} + static int hfi_f2h_main(void *arg) { struct adreno_device *adreno_dev = arg; @@ -849,8 +906,9 @@ static int hfi_f2h_main(void *arg) while (!kthread_should_stop()) { wait_event_interruptible(hfi->f2h_wq, - (!llist_empty(&hfi->f2h_msglist) && - !kthread_should_stop())); + ((!llist_empty(&hfi->f2h_msglist) || + !llist_empty(&hfi->f2h_secondary_list)) + && !kthread_should_stop())); if (kthread_should_stop()) break; @@ -868,6 +926,16 @@ static int hfi_f2h_main(void *arg) kmem_cache_free(f2h_cache, pkt); } + + /* Process packets on the secondary list after the primary list */ + list = llist_del_all(&hfi->f2h_secondary_list); + list = llist_reverse_order(list); + llist_for_each_entry_safe(pkt, tmp, list, node) { + if (MSG_HDR_GET_ID(pkt->rcvd[0]) == F2H_MSG_LOG_BLOCK) + process_log_block(adreno_dev, pkt->rcvd); + + kmem_cache_free(f2h_cache, pkt); + } } return 0; diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h index 70635b60f6ff..e0b286d78fa9 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h +++ b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.h @@ -117,6 +117,8 @@ struct a6xx_hwsched_hfi { struct task_struct *f2h_task; /** @f2h_msglist: List of gmu fw to host packets */ struct llist_head f2h_msglist; + /** @f2h_secondary_list: List of host profile packets from GMU */ + struct llist_head f2h_secondary_list; /** @f2h_wq: Waitqueue for the f2h_task */ wait_queue_head_t f2h_wq; }; diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index d8686da4a748..17e0cfe09780 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -173,6 +173,27 @@ TRACE_EVENT(gmu_ao_sync, ) ); +TRACE_EVENT(gmu_event, + TP_PROTO(u32 *event_info), + TP_ARGS(event_info), + TP_STRUCT__entry( + __field(u32, event) + __field(u32, ticks) + __field(u32, data1) + __field(u32, data2) + ), + TP_fast_assign( + __entry->event = event_info[0]; + __entry->ticks = event_info[1]; + __entry->data1 = event_info[2]; + __entry->data2 = event_info[3]; + ), + TP_printk( + "event=%08u ticks=%08u data1=%08x data2=%08x", + __entry->event, __entry->ticks, __entry->data1, __entry->data2 + ) +); + TRACE_EVENT(adreno_cmdbatch_sync, TP_PROTO(unsigned int ctx_id, unsigned int ctx_prio, unsigned int timestamp, uint64_t ticks),