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),