Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b912747e authored by Sushmita Susheelendra's avatar Sushmita Susheelendra
Browse files

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: default avatarSushmita Susheelendra <ssusheel@codeaurora.org>
parent 4381c344
Loading
Loading
Loading
Loading
+6 −6
Original line number Diff line number Diff line
@@ -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,
+8 −0
Original line number Diff line number Diff line
@@ -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
+71 −3
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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;
};
+21 −0
Original line number Diff line number Diff line
@@ -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),