mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 15:49:17 -04:00
Merge "msm: kgsl: Add support for GMU log streaming"
This commit is contained in:
commit
a9dae49894
6 changed files with 149 additions and 9 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
Loading…
Reference in a new issue