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

Commit 258b321e authored by Carter Cooper's avatar Carter Cooper
Browse files

msm: kgsl: Implement HFI version 2.0



Make the required changes to enable HFI version 2.0
Align packets to 16 bytes, remove message type POST,
reuse CMD messages' IDs in ACKs, and add AB table and
new HFI message. Make changes backwards compatible.

Change-Id: I005806404e1287c928c583e4cae861ae82b0728b
Signed-off-by: default avatarKyle Piefer <kpiefer@codeaurora.org>
Signed-off-by: default avatarGeorge Shen <sqiao@codeaurora.org>
Signed-off-by: default avatarOleg Perelet <operelet@codeaurora.org>
Signed-off-by: default avatarCarter Cooper <ccooper@codeaurora.org>
parent 113bedd5
Loading
Loading
Loading
Loading
+15 −6
Original line number Diff line number Diff line
@@ -949,6 +949,7 @@ static void a6xx_start(struct adreno_device *adreno_dev)
		int result;
		struct gmu_device *gmu = &device->gmu;
		struct device *dev = &gmu->pdev->dev;
		struct hfi_lmconfig_cmd cmd;

		kgsl_gmu_regwrite(device, A6XX_GPU_GMU_CX_GMU_PWR_THRESHOLD,
			GPU_LIMIT_THRESHOLD_ENABLE | lm_limit(adreno_dev));
@@ -959,7 +960,15 @@ static void a6xx_start(struct adreno_device *adreno_dev)
		gmu->bcl_config = 0;
		gmu->lm_dcvs_level = 0;

		result = hfi_send_req(gmu, H2F_MSG_LM_CFG, NULL);
		cmd.limit_conf = gmu->lm_config;
		cmd.bcl_conf = gmu->bcl_config;
		cmd.lm_enable_bitmask = 0;

		if (gmu->lm_dcvs_level <= MAX_GX_LEVELS)
			cmd.lm_enable_bitmask =
				(1 << (gmu->lm_dcvs_level + 1)) - 1;

		result = hfi_send_req(gmu, H2F_MSG_LM_CFG, &cmd);
		if (result)
			dev_err(dev, "Failure enabling limits management (%d)\n",
			result);
@@ -1800,9 +1809,9 @@ static int a6xx_notify_slumber(struct kgsl_device *device)
		a6xx_sptprac_disable(adreno_dev);

	if (!ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
		struct hfi_dcvs_vote req = {
			.perf_idx = perf_idx,
			.bw_idx = bus_level,
		struct hfi_prep_slumber_cmd req = {
			.freq = perf_idx,
			.bw = bus_level,
		};

		ret = hfi_send_req(gmu, H2F_MSG_PREPARE_SLUMBER, &req);
@@ -2062,10 +2071,10 @@ static int a6xx_gmu_dcvs_nohfi(struct kgsl_device *device,
	struct gmu_device *gmu = &device->gmu;
	int ret;

	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_ACK_OPTION, ACK_NONBLOCK);
	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_ACK_OPTION, DCVS_ACK_NONBLOCK);

	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_PERF_SETTING,
			FREQ_VOTE(perf_idx, OPTION_AT_LEAST));
			FREQ_VOTE(perf_idx, CLKSET_OPTION_ATLEAST));

	kgsl_gmu_regwrite(device, A6XX_GMU_DCVS_BW_SETTING, BW_VOTE(bw_idx));

+74 −14
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ struct gmu_iommu_context {
	struct iommu_domain *domain;
};

#define HFIMEM_SIZE SZ_16K
#define HFIMEM_SIZE (HFI_QUEUE_SIZE * (HFI_QUEUE_MAX + 1))

#define DUMPMEM_SIZE SZ_16K

@@ -363,6 +363,7 @@ static void gmu_kmem_close(struct gmu_device *gmu)


	gmu->hfi_mem = NULL;
	gmu->bw_mem = NULL;
	gmu->dump_mem = NULL;

	/* Unmap all memories in GMU kernel memory pool */
@@ -417,6 +418,12 @@ static int gmu_memory_probe(struct gmu_device *gmu, struct device_node *node)
		goto err_ret;
	}

	gmu->bw_mem = allocate_gmu_kmem(gmu, BWMEM_SIZE, IOMMU_READ);
	if (IS_ERR(gmu->bw_mem)) {
		ret = PTR_ERR(gmu->bw_mem);
		goto err_ret;
	}

	/* Allocates & maps GMU crash dump memory */
	gmu->dump_mem = allocate_gmu_kmem(gmu, DUMPMEM_SIZE,
				(IOMMU_READ | IOMMU_WRITE));
@@ -446,30 +453,30 @@ int gmu_dcvs_set(struct gmu_device *gmu,
	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct hfi_dcvs_vote req = {
		.ack_type = ACK_NONBLOCK,
		.perf_idx = INVALID_DCVS_IDX,
		.bw_idx = INVALID_DCVS_IDX,
	struct hfi_gx_bw_perf_vote_cmd req = {
		.ack_type = DCVS_ACK_NONBLOCK,
		.freq = INVALID_DCVS_IDX,
		.bw = INVALID_DCVS_IDX,
	};

	if (gpu_pwrlevel < gmu->num_gpupwrlevels - 1)
		req.perf_idx = gmu->num_gpupwrlevels - gpu_pwrlevel - 1;
		req.freq = gmu->num_gpupwrlevels - gpu_pwrlevel - 1;

	if (bus_level < gmu->num_bwlevels && bus_level > 0)
		req.bw_idx = bus_level;
		req.bw = bus_level;

	if ((req.perf_idx == INVALID_DCVS_IDX) &&
		(req.bw_idx == INVALID_DCVS_IDX))
	if ((req.freq == INVALID_DCVS_IDX) &&
		(req.bw == INVALID_DCVS_IDX))
		return -EINVAL;

	if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG)) {
		int ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev,
			GMU_DCVS_NOHFI, req.perf_idx, req.bw_idx);
			GMU_DCVS_NOHFI, req.freq, req.bw);

		if (ret) {
			dev_err_ratelimited(&gmu->pdev->dev,
				"Failed to set GPU perf idx %d, bw idx %d\n",
				req.perf_idx, req.bw_idx);
				req.freq, req.bw);

			adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
			adreno_dispatcher_schedule(device);
@@ -718,6 +725,35 @@ static void build_rpmh_bw_votes(struct gmu_bw_votes *rpmh_vote,
	}
}

/* TODO: Remove this and use the actual bus API */
#define GET_IB_VAL(i)	((i) & 0x3FFF)
#define GET_AB_VAL(i)	(((i) >> 14) & 0x3FFF)

static void build_rpmh_bw_buf(struct gmu_device *gmu)
{
	struct hfi_bwbuf *bwbuf = gmu->bw_mem->hostptr;
	struct rpmh_votes_t *votes = &gmu->rpmh_votes;
	unsigned int i, val;

	/* TODO: wait for IB/AB query API ready */

	/* Build from DDR votes in case IB/AB query API fail */
	for (i = 0; i < gmu->num_bwlevels; i++) {
		/* FIXME: wait for HPG to specify which node has IB/AB
		 * node 0 for now
		 */
		/* Get IB val */
		val = GET_IB_VAL(votes->ddr_votes.cmd_data[i][0]);
		/* If IB val not set, use AB val */
		if (val == 0)
			val = GET_AB_VAL(votes->ddr_votes.cmd_data[i][0]);

		/* Set only vote data */
		bwbuf->arr[i] &= 0xFFFF;
		bwbuf->arr[i] |= (val << 16);
	}
}

/*
 * gmu_bus_vote_init - initialized RPMh votes needed for bw scaling by GMU.
 * @gmu: Pointer to GMU device
@@ -755,6 +791,8 @@ static int gmu_bus_vote_init(struct gmu_device *gmu, struct kgsl_pwrctrl *pwr)

	build_rpmh_bw_votes(&votes->cnoc_votes, gmu->num_cnocbwlevels, hdl);

	build_rpmh_bw_buf(gmu);

out:
	kfree(usecases);

@@ -766,7 +804,7 @@ static int gmu_rpmh_init(struct gmu_device *gmu, struct kgsl_pwrctrl *pwr)
	struct rpmh_arc_vals gfx_arc, cx_arc, mx_arc;
	int ret;

	/* Populate BW vote table */
	/* Initialize BW tables */
	ret = gmu_bus_vote_init(gmu, pwr);
	if (ret)
		return ret;
@@ -968,6 +1006,10 @@ static int gmu_gpu_bw_probe(struct gmu_device *gmu)
{
	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
	struct msm_bus_scale_pdata *bus_scale_table;
	struct msm_bus_paths *usecase;
	struct msm_bus_vectors *vector;
	struct hfi_bwbuf *bwbuf = gmu->bw_mem->hostptr;
	int i;

	bus_scale_table = msm_bus_cl_get_pdata(device->pdev);
	if (bus_scale_table == NULL) {
@@ -982,6 +1024,25 @@ static int gmu_gpu_bw_probe(struct gmu_device *gmu)
		return -ENODEV;
	}

	/* 0-15: num levels; 16-31: arr offset in bytes */
	bwbuf->hdr[0] = (12 << 16) | (bus_scale_table->num_usecases & 0xFFFF);
	/* 0-15: element size in bytes; 16-31: data size in bytes */
	bwbuf->hdr[1] = (2 << 16) | 4;
	/* 0-15: bw val offset in bytes; 16-31: vote data offset in bytes */
	bwbuf->hdr[2] = (2 << 16) | 0;

	for (i = 0; i < bus_scale_table->num_usecases; i++) {
		usecase = &bus_scale_table->usecase[i];
		vector = &usecase->vectors[0];
		/* Clear bw val */
		bwbuf->arr[i] &= 0xFFFF0000;
		/* Set bw val if not first entry */
		if (i)
			bwbuf->arr[i] |=
				(DIV_ROUND_UP_ULL(vector->ib, 1048576)
				 & 0xFFFF);
	}

	return 0;
}

@@ -1611,7 +1672,6 @@ void gmu_remove(struct kgsl_device *device)
		gmu->reg_virt = NULL;
	}

	if (gmu->hfi_mem || gmu->dump_mem)
	gmu_memory_close(&device->gmu);

	for (i = 0; i < MAX_GMU_CLKS; i++) {
+4 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#define FENCE_STATUS_WRITEDROPPED0_MASK 0x1
#define FENCE_STATUS_WRITEDROPPED1_MASK 0x2

#define BWMEM_SIZE	(12 + (4 * NUM_BW_LEVELS))	/*in bytes*/

/* Bitmask for GPU low power mode enabling and hysterisis*/
#define SPTP_ENABLE_MASK (BIT(2) | BIT(0))
#define IFPC_ENABLE_MASK (BIT(1) | BIT(0))
@@ -183,6 +185,7 @@ enum gpu_idle_level {
 * @gmu_interrupt_num: GMU interrupt number
 * @fw_image: descriptor of GMU memory that has GMU image in it
 * @hfi_mem: pointer to HFI shared memory
 * @bw_mem: pointer to BW data indirect buffer memory
 * @dump_mem: pointer to GMU debug dump memory
 * @hfi: HFI controller
 * @lm_config: GPU LM configuration data
@@ -220,6 +223,7 @@ struct gmu_device {
	unsigned int gmu_interrupt_num;
	struct gmu_memdesc fw_image;
	struct gmu_memdesc *hfi_mem;
	struct gmu_memdesc *bw_mem;
	struct gmu_memdesc *dump_mem;
	struct kgsl_hfi hfi;
	unsigned int lm_config;
+199 −247

File changed.

Preview size limit exceeded, changes collapsed.

+384 −70
Original line number Diff line number Diff line
@@ -16,15 +16,34 @@
#include <linux/types.h>

#define HFI_QUEUE_SIZE			SZ_4K		/* bytes */
#define MAX_RSP_PAYLOAD_SIZE		16		/* dwords */
#define MAX_RCVD_PAYLOAD_SIZE		16		/* dwords */
#define MAX_RCVD_SIZE			(MAX_RCVD_PAYLOAD_SIZE + 3) /* dwords */
#define HFI_MAX_MSG_SIZE		(SZ_1K>>2)	/* dwords */

/* Below section is for all structures related to HFI queues */
#define HFI_QUEUE_MAX 3
#define HFI_QUEUE_DEFAULT_CNT 3
#define HFI_QUEUE_DISPATCH_CNT 1
#define HFI_QUEUE_MAX (HFI_QUEUE_DEFAULT_CNT + HFI_QUEUE_DISPATCH_CNT)

#define HFI_CMD_ID 0
#define HFI_MSG_ID 1
#define HFI_DBG_ID 2
#define HFI_DSP_ID_0 3

#define HFI_CMD_IDX 0
#define HFI_MSG_IDX 1
#define HFI_DBG_IDX 2
#define HFI_DSP_IDX_BASE 3
#define HFI_DSP_IDX_0 3

/* HTOF queue priority, 1 is highest priority */
#define HFI_CMD_PRI 10
#define HFI_MSG_PRI 10
#define HFI_DBG_PRI 40
#define HFI_DSP_PRI_0 20

#define HFI_RSP_TIMEOUT 5000 /* msec */
#define HFI_H2F_CMD_IRQ_MASK BIT(0)

#define HFI_QUEUE_OFFSET(i)		\
		((sizeof(struct hfi_queue_table)) + \
@@ -45,6 +64,47 @@
#define HFI_IRQ_MASK			(HFI_IRQ_MSGQ_MASK |\
					HFI_IRQ_CM3_FAULT_MASK)

#define CLKSET_OPTION_DEFAULT 0
#define CLKSET_OPTION_CLOSEST 1
#define CLKSET_OPTION_ATMOST 2
#define CLKSET_OPTION_ATLEAST 3

#define DCVS_ACK_NONBLOCK 0
#define DCVS_ACK_BLOCK 1

#define HFI_FEATURE_DCVS	0
#define HFI_FEATURE_ECP		1
#define HFI_FEATURE_PREEMPTION	2
#define HFI_FEATURE_CLOCKS_ON	3
#define HFI_FEATURE_BUS_ON	4
#define HFI_FEATURE_RAIL_ON	5
#define HFI_FEATURE_HWCG	6
#define HFI_FEATURE_LM		7
#define HFI_FEATURE_THROTTLE	8
#define HFI_FEATURE_IFPC	9
#define HFI_FEATURE_NAP		10
#define HFI_FEATURE_BCL		11
#define HFI_FEATURE_ACD		12
#define HFI_FEATURE_DIDT	13

#define HFI_VALUE_FT_POLICY		100
#define HFI_VALUE_RB_MAX_CMDS		101
#define HFI_VALUE_CTX_MAX_CMDS		102
#define HFI_VALUE_ADDRESS		103
#define HFI_VALUE_MAX_GPU_PERF_INDEX	104
#define HFI_VALUE_MIN_GPU_PERF_INDEX	105
#define HFI_VALUE_MAX_BW_PERF_INDEX	106
#define HFI_VALUE_MIN_BW_PERF_INDEX	107
#define HFI_VALUE_MAX_GPU_THERMAL_INDEX	108
#define HFI_VALUE_GPUCLK		109
#define HFI_VALUE_CLK_TIME		110
#define HFI_VALUE_LOG_LEVEL		111
#define HFI_VALUE_LOG_EVENT_ON		112
#define HFI_VALUE_LOG_EVENT_OFF		113
#define HFI_VALUE_DCVS_OBJ		114

#define HFI_VALUE_GLOBAL_TOKEN		0xFFFFFFFF

/**
 * struct hfi_queue_table_header - HFI queue table structure
 * @version: HFI protocol version
@@ -99,28 +159,11 @@ struct hfi_queue_table {
	struct hfi_queue_header qhdr[HFI_QUEUE_MAX];
};

/* HTOF queue priority, 1 is highest priority */
enum hfi_h2f_qpri {
	HFI_H2F_QPRI_CMD = 10,
	HFI_H2F_QPRI_DISPATCH_P0 = 20,
	HFI_H2F_QPRI_DISPATCH_P1 = 21,
	HFI_H2F_QPRI_DISPATCH_P2 = 22,
};

/* FTOH queue priority, 1 is highest priority */
enum hfi_f2h_qpri {
	HFI_F2H_QPRI_MSG = 10,
	HFI_F2H_QPRI_DEBUG = 40,
};

#define HFI_RSP_TIMEOUT 5000 /* msec */
#define HFI_H2F_CMD_IRQ_MASK BIT(0)

enum hfi_msg_type {
	HFI_MSG_CMD = 0,
	HFI_MSG_POST = 1,
	HFI_MSG_ACK = 2,
	HFI_MSG_INVALID = 3
	HFI_MSG_CMD = 0, /* V1 and V2 */
	HFI_MSG_ACK = 1, /* V2 only */
	HFI_V1_MSG_POST = 1, /* V1 only */
	HFI_V1_MSG_ACK = 2, /* V1 only */
};

#define H2F_MSG_INIT		0
@@ -129,14 +172,32 @@ enum hfi_msg_type {
#define H2F_MSG_BW_VOTE_TBL	3
#define H2F_MSG_PERF_TBL	4
#define H2F_MSG_TEST		5
#define H2F_MSG_START		10
#define H2F_MSG_FEATURE_CTRL	11
#define H2F_MSG_GET_VALUE	12
#define H2F_MSG_SET_VALUE	13
#define H2F_MSG_CORE_FW_START	14
#define F2H_MSG_MEM_ALLOC	20
#define H2F_MSG_GX_BW_PERF_VOTE	30
#define H2F_MSG_FW_HALT		32
#define H2F_MSG_PREPARE_SLUMBER	33
#define F2H_MSG_ERR		100
#define F2H_MSG_DEBUG		101
#define F2H_MSG_ACK		126
#define H2F_MSG_ACK		127

#define F2H_MSG_GMU_CNTR_REGISTER	110
#define F2H_MSG_GMU_CNTR_RELEASE	111
#define F2H_MSG_ACK		126 /* Deprecated for v2.0*/
#define H2F_MSG_ACK		127 /* Deprecated for v2.0*/
#define H2F_MSG_REGISTER_CONTEXT	128
#define H2F_MSG_UNREGISTER_CONTEXT	129
#define H2F_MSG_ISSUE_CMD	130
#define H2F_MSG_ISSUE_CMD_RAW	131
#define H2F_MSG_TS_NOTIFY	132
#define F2H_MSG_TS_RETIRE	133
#define H2F_MSG_CONTEXT_POINTERS	134
#define H2F_MSG_CONTEXT_RULE	140 /* AKA constraint */
#define F2H_MSG_CONTEXT_BAD	150

#define NUM_BW_LEVELS		100
#define MAX_GX_LEVELS		16
#define MAX_CX_LEVELS		4
#define MAX_CNOC_LEVELS		2
@@ -148,13 +209,7 @@ enum hfi_msg_type {
#error "CNOC levels cannot exceed GX levels"
#endif

struct hfi_msg_rsp {
	uint32_t hdr;
	uint32_t ret_hdr;
	uint32_t error;
	uint32_t payload[MAX_RSP_PAYLOAD_SIZE];
};

/* H2F */
struct hfi_gmu_init_cmd {
	uint32_t hdr;
	uint32_t seg_id;
@@ -163,11 +218,13 @@ struct hfi_gmu_init_cmd {
	uint32_t boot_state;
};

/* H2F */
struct hfi_fw_version_cmd {
	uint32_t hdr;
	uint32_t supported_ver;
};

/* H2F */
struct hfi_lmconfig_cmd {
	uint32_t hdr;
	uint32_t limit_conf;
@@ -175,6 +232,14 @@ struct hfi_lmconfig_cmd {
	uint32_t lm_enable_bitmask;
};

#define ARC_VOTE_GET_PRI(_v) ((_v) & 0xFF)
#define ARC_VOTE_GET_SEC(_v) (((_v) >> 8) & 0xFF)
#define ARC_VOTE_GET_VLVL(_v) (((_v) >> 16) & 0xFFFF)

#define ARC_VOTE_SET(pri, sec, vlvl) \
	((((vlvl) & 0xFFFF) << 16) | (((sec) & 0xFF) << 8) | ((pri) & 0xFF))

/* H2F */
struct hfi_bwtable_cmd {
	uint32_t hdr;
	uint32_t bw_level_num;
@@ -188,22 +253,18 @@ struct hfi_bwtable_cmd {
	uint32_t ddr_cmd_data[MAX_GX_LEVELS][MAX_BW_CMDS];
};

struct hfi_test_cmd {
	uint32_t hdr;
struct hfi_bwbuf {
	uint32_t hdr[3];
	uint32_t arr[NUM_BW_LEVELS];
};

#define ARC_VOTE_GET_PRI(_v) ((_v) & 0xFF)
#define ARC_VOTE_GET_SEC(_v) (((_v) >> 8) & 0xFF)
#define ARC_VOTE_GET_VLVL(_v) (((_v) >> 16) & 0xFFFF)

#define ARC_VOTE_SET(pri, sec, vlvl) \
	((((vlvl) & 0xFFFF) << 16) | (((sec) & 0xFF) << 8) | ((pri) & 0xFF))

struct opp_desc {
	uint32_t vote;
	uint32_t acd;
	uint32_t freq;
};

/* H2F */
struct hfi_dcvstable_cmd {
	uint32_t hdr;
	uint32_t gpu_level_num;
@@ -212,26 +273,124 @@ struct hfi_dcvstable_cmd {
	struct opp_desc cx_votes[MAX_CX_LEVELS];
};

enum fw_clkset_options {
	OPTION_DEFAULT = 0,
	OPTION_CLOSEST = 1,
	OPTION_AT_MOST = 2,
	OPTION_AT_LEAST = 3,
	OPTION_INVALID = 4
/* H2F */
struct hfi_test_cmd {
	uint32_t hdr;
	uint32_t data;
};

/* H2F */
struct hfi_start_cmd {
	uint32_t hdr;
};

/* H2F */
struct hfi_feature_ctrl_cmd {
	uint32_t hdr;
	uint32_t feature;
	uint32_t enable;
	uint32_t data;
};

/* H2F */
struct hfi_get_value_cmd {
	uint32_t hdr;
	uint32_t type;
	uint32_t subtype;
};

enum rpm_ack_type {
	ACK_NONBLOCK = 0,
	ACK_BLOCK = 1,
	ACK_INVALID = 2,
/* Internal */
struct hfi_get_value_req {
	struct hfi_get_value_cmd cmd;
	uint32_t data[16];
};

struct hfi_dcvs_vote {
	uint32_t perf_idx;
	uint32_t bw_idx;
	enum rpm_ack_type ack_type;
/* F2H */
struct hfi_get_value_reply_cmd {
	uint32_t hdr;
	uint32_t req_hdr;
	uint32_t data[16];
};

/* H2F */
struct hfi_set_value_cmd {
	uint32_t hdr;
	uint32_t type;
	uint32_t subtype;
	uint32_t data;
};

/* H2F */
struct hfi_core_fw_start_cmd {
	uint32_t hdr;
	uint32_t handle;
};

/* CP/GFX pipeline can access, The mem_kind may imply restrictions for non-CP */
#define MEMFLAG_GFX_ACC                  BIT(0)
/* Buffer has APRIV protection in GFX PTEs */
#define MEMFLAG_GFX_PRIV                 BIT(1)
/* Buffer is read-write for GFX PTEs. A 0 indicates read-only */
#define MEMFLAG_GFX_WRITEABLE            BIT(2)
/* GMU can access */
#define MEMFLAG_GMU_ACC                  BIT(3)
/* Buffer has APRIV protection in GMU PTEs */
#define MEMFLAG_GMU_PRIV                 BIT(4)
/* Buffer is read-write for GMU PTEs. A 0 indicates read-only */
#define MEMFLAG_GMU_WRITEABLE            BIT(5)
/* Buffer is located in GMU's non-cached bufferable VA range */
#define MEMFLAG_GMU_BUFFERABLE           BIT(6)
/* Buffer is located in GMU's cacheable VA range */
#define MEMFLAG_GMU_CACHEABLE            BIT(7)
/* Host can access */
#define MEMFLAG_HOST_ACC                 BIT(8)
/*
 * Request that Host initialize the buffer.
 * Implies zero-init, unless Memkind implies otherwise
 */
#define MEMFLAG_HOST_INIT                BIT(9)

#define HFI_MEMKIND_GENERIC		0
#define HFI_MEMKIND_RB			1
#define HFI_MEMKIND_MEMSTORE		2
#define HFI_MEMKIND_CSW_SMMU_INFO	3
#define HFI_MEMKIND_CSW_PRIV_NON_SECURE	4
#define HFI_MEMKIND_CSW_PRIV_SECURE	5
#define HFI_MEMKIND_CSW_NON_PRIV	6
#define HFI_MEMKIND_CSW_COUNTER		7
#define HFI_MEMKIND_CTXTREC_PERF_CNTR_SAVE_RESTORE	8
#define HFI_MEMKIND_CTXTREC_PREEMPT_CNTR	9
#define HFI_MEMKIND_SYS_LOG		10
#define HFI_MEMKIND_CRASH_DUMP		11
#define HFI_MEMKIND_MMIO_DPU		12
#define HFI_MEMKIND_MMIO_TCSR		13
#define HFI_MEMKIND_MMIO_QDSS_STM	14

struct hfi_mem_alloc_desc {
	uint64_t gpu_addr;
	uint32_t flags;
	uint32_t mem_kind;
	uint32_t host_mem_handle;
	uint32_t gmu_mem_handle;
	uint32_t gmu_addr;
	uint32_t size; /* Bytes */
};

/* F2H */
struct hfi_mem_alloc_cmd {
	uint32_t hdr;
	uint32_t reserved; /* Padding to ensure alignment of 'desc' below */
	struct hfi_mem_alloc_desc desc;
};

/* H2F */
struct hfi_mem_alloc_reply_cmd {
	uint32_t hdr;
	uint32_t req_hdr;
	struct hfi_mem_alloc_desc desc;
};

/* H2F */
struct hfi_gx_bw_perf_vote_cmd {
	uint32_t hdr;
	uint32_t ack_type;
@@ -239,47 +398,203 @@ struct hfi_gx_bw_perf_vote_cmd {
	uint32_t bw;
};

/* H2F */
struct hfi_fw_halt_cmd {
	uint32_t hdr;
	uint32_t en_halt;
};

/* H2F */
struct hfi_prep_slumber_cmd {
	uint32_t hdr;
	uint32_t init_bw_idx;
	uint32_t init_perf_idx;
	uint32_t bw;
	uint32_t freq;
};

struct hfi_fw_err_msg {
/* F2H */
struct hfi_err_cmd {
	uint32_t hdr;
	uint32_t error_code;
	uint32_t data[2];
};

struct hfi_debug_msg {
/* F2H */
struct hfi_debug_cmd {
	uint32_t hdr;
	uint32_t type;
	uint32_t timestamp;
	uint32_t data;
};

/* F2H */
struct hfi_gmu_cntr_register_cmd {
	uint32_t hdr;
	uint32_t group_id;
	uint32_t countable;
};

/* H2F */
struct hfi_gmu_cntr_register_reply_cmd {
	uint32_t hdr;
	uint32_t req_hdr;
	uint32_t group_id;
	uint32_t countable;
	uint64_t counter_addr;
};

/* F2H */
struct hfi_gmu_cntr_release_cmd {
	uint32_t hdr;
	uint32_t group_id;
	uint32_t countable;
};

#define CTXT_FLAG_PMODE			0x00000001
#define CTXT_FLAG_SWITCH_INTERNAL	0x00000002
#define CTXT_FLAG_SWITCH		0x00000008
#define CTXT_FLAG_NOTIFY		0x00000020
#define CTXT_FLAG_NO_FAULT_TOLERANCE	0x00000200
#define CTXT_FLAG_PWR_RULE		0x00000800
#define CTXT_FLAG_PRIORITY_MASK		0x0000F000
#define CTXT_FLAG_IFH_NOP		0x00010000
#define CTXT_FLAG_SECURE		0x00020000
#define CTXT_FLAG_TYPE_MASK		0x01F00000
#define CTXT_FLAG_TYPE_SHIFT		20
#define CTXT_FLAG_TYPE_ANY		0
#define CTXT_FLAG_TYPE_GL		1
#define CTXT_FLAG_TYPE_CL		2
#define CTXT_FLAG_TYPE_C2D		3
#define CTXT_FLAG_TYPE_RS		4
#define CTXT_FLAG_TYPE_UNKNOWN		0x1E
#define CTXT_FLAG_PREEMPT_STYLE_MASK	0x0E000000
#define CTXT_FLAG_PREEMPT_STYLE_SHIFT	25
#define CTXT_FLAG_PREEMPT_STYLE_ANY	0
#define CTXT_FLAG_PREEMPT_STYLE_RB	1
#define CTXT_FLAG_PREEMPT_STYLE_FG	2

/* H2F */
struct hfi_register_ctxt_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t flags;
	uint64_t pt_addr;
	uint32_t ctxt_idr;
	uint32_t ctxt_bank;
};

/* H2F */
struct hfi_unregister_ctxt_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t ts;
};

#define CMDBATCH_SWITCH		CTXT_FLAG_SWITCH
#define CMDBATCH_NOTIFY		CTXT_FLAG_NOTIFY
#define CMDBATCH_PROFILING	0x00000010
#define CMDBATCH_EOF		0x00000100
#define CMDBATCH_PWR_STRICT	CTXT_FLAG_PWR_RULE

struct hfi_issue_ib {
	uint64_t addr;
	uint32_t size;
};

/* H2F */
struct hfi_issue_cmd_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t flags;
	uint32_t ts;
	uint32_t count;
	struct hfi_issue_ib *ibs[];
};

/* Internal */
struct hfi_issue_cmd_req {
	uint32_t queue;
	uint32_t ctxt_id;
	struct hfi_issue_cmd_cmd cmd;
};

/* H2F */
/* The length of *buf will be embedded in the hdr */
struct hfi_issue_cmd_raw_cmd {
	uint32_t hdr;
	uint32_t *buf;
};

/* Internal */
struct hfi_issue_cmd_raw_req {
	uint32_t queue;
	uint32_t ctxt_id;
	uint32_t len;
	uint32_t *buf;
};

/* H2F */
struct hfi_ts_notify_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t ts;
};

#define TS_RETIRE_FLUSH	1
#define TS_RETIRE_ERROR	2
#define TS_RETIRE_PAST	3
#define TS_RETIRE_DONE	4

/* F2H */
struct hfi_ts_retire_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t ts;
	uint32_t type;
};

/* H2F */
struct hfi_context_pointers_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint64_t sop_addr;
	uint64_t eop_addr;
};

/* H2F */
struct hfi_context_rule_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t type;
	uint32_t status;
};

/* F2H */
struct hfi_context_bad_cmd {
	uint32_t hdr;
	uint32_t ctxt_id;
	uint32_t status;
	uint32_t error;
};

/* H2F */
struct hfi_context_bad_reply_cmd {
	uint32_t hdr;
	uint32_t req_hdr;
};

/**
 * struct pending_msg - data structure to track outstanding HFI
 * struct pending_cmd - data structure to track outstanding HFI
 *	command messages
 * @msg_complete: a blocking mechanism for sender to wait for ACK
 * @node: a node in pending message queue
 * @msg_id: the ID of the command message pending for ACK
 * @seqnum: the seqnum of the command message pending for ACK.
 *	together with msg_id, are used to correlate a receiving ACK
 *	to a pending cmd message
 * @sent_hdr: copy of outgoing header for response comparison
 * @results: the payload of received return message (ACK)
 */
struct pending_msg {
struct pending_cmd {
	struct completion msg_complete;
	struct list_head node;
	uint32_t msg_id;
	uint32_t seqnum;
	struct hfi_msg_rsp results;
	uint32_t sent_hdr;
	uint32_t results[MAX_RCVD_SIZE];
};

/**
@@ -302,7 +617,6 @@ struct kgsl_hfi {
	struct tasklet_struct tasklet;
	uint32_t version;
	atomic_t seqnum;
	bool gmu_init_done;
};

struct gmu_device;