mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 15:49:17 -04:00
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 <ssusheel@codeaurora.org>
This commit is contained in:
parent
4381c3443b
commit
b912747ec7
5 changed files with 108 additions and 9 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
Loading…
Reference in a new issue