Merge "msm: kgsl: Add support for GMU log streaming"

This commit is contained in:
qctecmdr 2020-09-21 11:51:04 -07:00 • committed by Gerrit - the friendly Code Review server
commit a9dae49894
6 changed files with 149 additions and 9 deletions

View file

@ -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;

View file

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

View file

@ -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

View file

@ -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)
{
@ -234,10 +273,18 @@ 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)
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);
@ -832,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;
@ -841,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;
@ -860,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;

View file

@ -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;
};

View file

@ -159,6 +159,41 @@ 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(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),