From 88cb36d31e1ad955bc1729f2d21c919731509da6 Mon Sep 17 00:00:00 2001 From: Sushmita Susheelendra Date: Wed, 2 Sep 2020 10:12:26 -0600 Subject: [PATCH 1/3] msm: kgsl: Add a sync event to map GMU events to ftrace timeline GMU events will be streamed to the host if GMU log streaming is enabled. Being able to view GMU events on the same timeline as GPU and host events is helpful for profiling. Add a sync event to map GMU AO counter ticks to the ftrace timeline just before bringing the GMU out of reset. Change-Id: I7e2696f4d0d8666a2fcdfccb358619277e5949b8 Signed-off-by: Sushmita Susheelendra --- drivers/gpu/msm/adreno_a6xx_gmu.c | 19 +++++++++++++++++++ drivers/gpu/msm/adreno_trace.h | 14 ++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/gpu/msm/adreno_a6xx_gmu.c b/drivers/gpu/msm/adreno_a6xx_gmu.c index 4be6ff6b4c55..e44ee2182bde 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu.c @@ -19,6 +19,7 @@ #include "adreno.h" #include "adreno_a6xx.h" #include "adreno_hwsched.h" +#include "adreno_trace.h" #include "kgsl_bus.h" #include "kgsl_device.h" #include "kgsl_trace.h" @@ -415,6 +416,22 @@ static void a6xx_gmu_power_config(struct adreno_device *adreno_dev) RPMH_ENABLE_MASK); } +static void gmu_ao_sync_event(struct adreno_device *adreno_dev) +{ + unsigned long flags; + u64 ticks; + + local_irq_save(flags); + + /* Read GMU always on register */ + ticks = a6xx_read_alwayson(adreno_dev); + + /* Trace the GMU time to create a mapping to ftrace time */ + trace_gmu_ao_sync(ticks); + + local_irq_restore(flags); +} + int a6xx_gmu_device_start(struct adreno_device *adreno_dev) { struct kgsl_device *device = KGSL_DEVICE(adreno_dev); @@ -422,6 +439,8 @@ int a6xx_gmu_device_start(struct adreno_device *adreno_dev) u32 val = 0x00000100; u32 mask = 0x000001FF; + gmu_ao_sync_event(adreno_dev); + /* Check for 0xBABEFACE on legacy targets */ if (gmu->ver.core <= 0x20010004) { val = 0xBABEFACE; diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index bd9052e65c64..d8686da4a748 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -159,6 +159,20 @@ TRACE_EVENT(adreno_cmdbatch_retired, ) ); +TRACE_EVENT(gmu_ao_sync, + TP_PROTO(u64 ticks), + TP_ARGS(ticks), + TP_STRUCT__entry( + __field(u64, ticks) + ), + TP_fast_assign( + __entry->ticks = ticks; + ), + TP_printk( + "ticks=%llu", __entry->ticks + ) +); + TRACE_EVENT(adreno_cmdbatch_sync, TP_PROTO(unsigned int ctx_id, unsigned int ctx_prio, unsigned int timestamp, uint64_t ticks), From 4381c3443b1b4acdf04d35fa89e064940fff335a Mon Sep 17 00:00:00 2001 From: Sushmita Susheelendra Date: Tue, 15 Sep 2020 22:38:14 -0600 Subject: [PATCH 2/3] msm: kgsl: Fix message handling in hwsched hfi interrupt handler Do not process HFI messages on the message queue in the interrupt handler before interrupts are enabled on that queue. Otherwise, the interrupt handler will read it off the queue, and then the inline handler will not find any messages on the queue. Change-Id: I569f29250c27a1a74e206489ad8234b2be39d448 Signed-off-by: Sushmita Susheelendra --- drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c index 2b965e5bb584..bb90c9178aa5 100644 --- a/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c +++ b/drivers/gpu/msm/adreno_a6xx_hwsched_hfi.c @@ -234,6 +234,14 @@ static irqreturn_t a6xx_hwsched_hfi_handler(int irq, void *data) gmu_core_regread(device, A6XX_GMU_GMU2HOST_INTR_INFO, &status); gmu_core_regwrite(device, A6XX_GMU_GMU2HOST_INTR_CLR, hfi->irq_mask); + /* + * If interrupts are not enabled on the HFI message queue, + * the inline message processing loop will process it, + * else, process it here. + */ + if (!(hfi->irq_mask & HFI_IRQ_MSGQ_MASK)) + status &= ~HFI_IRQ_MSGQ_MASK; + if (status & HFI_IRQ_MSGQ_MASK) process_msgq_irq(adreno_dev); if (status & HFI_IRQ_DBGQ_MASK) From b912747ec749bdae7fa96651c686a8ccbc75e20a Mon Sep 17 00:00:00 2001 From: Sushmita Susheelendra Date: Tue, 15 Sep 2020 22:58:34 -0600 Subject: [PATCH 3/3] 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),