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

Commit a9dae498 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 423554d6 b912747e
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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;
+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
+79 −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)
{
@@ -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;
+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;
};
Loading