4f187642c8
It is possible that due to HLOS latency issues or the hfi interrupt handler didn't run or the f2h daemon didn't run in expected time. Hence, before timing out, inspect MSGQ one last time to see if the ack came or not. If the ack is present, log an error and move on. Change-Id: I6163681d1bc9d8cf5ea1ff0317fc4a95fcac4908 Signed-off-by: Pankaj Gupta <quic_gpankaj@quicinc.com>
1415 lines
37 KiB
C
1415 lines
37 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
|
* Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
#ifndef __ADRENO_HFI_H
|
|
#define __ADRENO_HFI_H
|
|
|
|
#include "kgsl_util.h"
|
|
|
|
#define HW_FENCE_QUEUE_SIZE SZ_4K
|
|
#define HFI_QUEUE_SIZE SZ_4K /* bytes, must be base 4dw */
|
|
#define MAX_RCVD_PAYLOAD_SIZE 16 /* dwords */
|
|
#define MAX_RCVD_SIZE (MAX_RCVD_PAYLOAD_SIZE + 3) /* dwords */
|
|
#define HFI_MAX_MSG_SIZE (SZ_1K)
|
|
|
|
#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
|
|
|
|
#define HFI_CMD_IDX_LEGACY 0
|
|
#define HFI_DSP_IDX_0_LEGACY 1
|
|
#define HFI_MSG_IDX_LEGACY 4
|
|
#define HFI_DBG_IDX_LEGACY 5
|
|
|
|
#define HFI_QUEUE_STATUS_DISABLED 0
|
|
#define HFI_QUEUE_STATUS_ENABLED 1
|
|
|
|
/* 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_IRQ_SIDEMSGQ_MASK BIT(1)
|
|
#define HFI_IRQ_DBGQ_MASK BIT(2)
|
|
#define HFI_IRQ_CM3_FAULT_MASK BIT(15)
|
|
#define HFI_IRQ_OOB_MASK GENMASK(31, 16)
|
|
#define HFI_IRQ_MASK (HFI_IRQ_SIDEMSGQ_MASK |\
|
|
HFI_IRQ_DBGQ_MASK |\
|
|
HFI_IRQ_CM3_FAULT_MASK)
|
|
|
|
#define DCVS_ACK_NONBLOCK 0
|
|
#define DCVS_ACK_BLOCK 1
|
|
|
|
#define HFI_FEATURE_DCVS 0
|
|
#define HFI_FEATURE_HWSCHED 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_FEATURE_DEPRECATED 14
|
|
#define HFI_FEATURE_CB 15
|
|
#define HFI_FEATURE_KPROF 16
|
|
#define HFI_FEATURE_BAIL_OUT_TIMER 17
|
|
#define HFI_FEATURE_GMU_STATS 18
|
|
#define HFI_FEATURE_DBQ 19
|
|
#define HFI_FEATURE_MINBW 20
|
|
#define HFI_FEATURE_CLX 21
|
|
#define HFI_FEATURE_LSR 23
|
|
#define HFI_FEATURE_LPAC 24
|
|
#define HFI_FEATURE_HW_FENCE 25
|
|
#define HFI_FEATURE_PERF_NORETAIN 26
|
|
#define HFI_FEATURE_DMS 27
|
|
#define HFI_FEATURE_AQE 29
|
|
|
|
/* Types to be used with H2F_MSG_TABLE */
|
|
enum hfi_table_type {
|
|
HFI_TABLE_BW_VOTE = 0,
|
|
HFI_TABLE_GPU_PERF = 1,
|
|
HFI_TABLE_DIDT = 2,
|
|
HFI_TABLE_ACD = 3,
|
|
HFI_TABLE_CLX_V1 = 4,
|
|
HFI_TABLE_CLX_V2 = 5,
|
|
HFI_TABLE_THERM = 6,
|
|
HFI_TABLE_DCVS_DATA = 7,
|
|
HFI_TABLE_MAX,
|
|
};
|
|
|
|
/* A6xx uses a different value for KPROF */
|
|
#define HFI_FEATURE_A6XX_KPROF 14
|
|
|
|
/* For Gen7 & Gen8 ACD */
|
|
#define F_PWR_ACD_CALIBRATE 78
|
|
|
|
#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_GROUP 111
|
|
#define HFI_VALUE_LOG_EVENT_ON 112
|
|
#define HFI_VALUE_LOG_EVENT_OFF 113
|
|
#define HFI_VALUE_DCVS_OBJ 114
|
|
#define HFI_VALUE_LM_CS0 115
|
|
#define HFI_VALUE_DBG 116
|
|
#define HFI_VALUE_BIN_TIME 117
|
|
#define HFI_VALUE_LOG_STREAM_ENABLE 119
|
|
#define HFI_VALUE_PREEMPT_COUNT 120
|
|
#define HFI_VALUE_CONTEXT_QUEUE 121
|
|
#define HFI_VALUE_GMU_AB_VOTE 122
|
|
#define HFI_VALUE_RB_GPU_QOS 123
|
|
#define HFI_VALUE_RB_IB_RULE 124
|
|
#define HFI_VALUE_GMU_WARMBOOT 125
|
|
#define HFI_VALUE_GLOBAL_TOKEN 0xFFFFFFFF
|
|
|
|
#define HFI_CTXT_FLAG_PMODE BIT(0)
|
|
#define HFI_CTXT_FLAG_SWITCH_INTERNAL BIT(1)
|
|
#define HFI_CTXT_FLAG_SWITCH BIT(3)
|
|
#define HFI_CTXT_FLAG_NOTIFY BIT(5)
|
|
#define HFI_CTXT_FLAG_NO_FAULT_TOLERANCE BIT(9)
|
|
#define HFI_CTXT_FLAG_PWR_RULE BIT(11)
|
|
#define HFI_CTXT_FLAG_PRIORITY_MASK GENMASK(15, 12)
|
|
#define HFI_CTXT_FLAG_IFH_NOP BIT(16)
|
|
#define HFI_CTXT_FLAG_SECURE BIT(17)
|
|
#define HFI_CTXT_FLAG_TYPE_MASK GENMASK(24, 20)
|
|
#define HFI_CTXT_FLAG_TYPE_ANY 0
|
|
#define HFI_CTXT_FLAG_TYPE_GL 1
|
|
#define HFI_CTXT_FLAG_TYPE_CL 2
|
|
#define HFI_CTXT_FLAG_TYPE_C2D 3
|
|
#define HFI_CTXT_FLAG_TYPE_RS 4
|
|
#define HFI_CTXT_FLAG_TYPE_VK 5
|
|
#define HFI_CTXT_FLAG_TYPE_UNKNOWN 0x1e
|
|
#define HFI_CTXT_FLAG_PREEMPT_STYLE_MASK GENMASK(27, 25)
|
|
#define HFI_CTXT_FLAG_PREEMPT_STYLE_ANY 0
|
|
#define HFI_CTXT_FLAG_PREEMPT_STYLE_RB 1
|
|
#define HFI_CTXT_FLAG_PREEMPT_STYLE_FG 2
|
|
|
|
/* Default sampling interval in units of 50 us */
|
|
#define HFI_FEATURE_GMU_STATS_INTERVAL 4
|
|
|
|
enum hfi_mem_kind {
|
|
/** @HFI_MEMKIND_GENERIC: Used for requesting generic memory */
|
|
HFI_MEMKIND_GENERIC = 0,
|
|
/** @HFI_MEMKIND_RB: Used for requesting ringbuffer memory */
|
|
HFI_MEMKIND_RB,
|
|
/** @HFI_MEMKIND_SCRATCH: Used for requesting scratch memory */
|
|
HFI_MEMKIND_SCRATCH,
|
|
/**
|
|
* @HFI_MEMKIND_CSW_SMMU_INFO: Used for requesting SMMU record for
|
|
* preemption context switching
|
|
*/
|
|
HFI_MEMKIND_CSW_SMMU_INFO,
|
|
/**
|
|
* @HFI_MEMKIND_CSW_PRIV_NON_SECURE: Used for requesting privileged non
|
|
* secure preemption records
|
|
*/
|
|
HFI_MEMKIND_CSW_PRIV_NON_SECURE,
|
|
/**
|
|
* @HFI_MEMKIND_CSW_PRIV_SECURE: Used for requesting privileged secure
|
|
* preemption records
|
|
*/
|
|
HFI_MEMKIND_CSW_PRIV_SECURE,
|
|
/**
|
|
* @HFI_MEMKIND_CSW_NON_PRIV: Used for requesting non privileged per
|
|
* context preemption buffer
|
|
*/
|
|
HFI_MEMKIND_CSW_NON_PRIV,
|
|
/**
|
|
* @HFI_MEMKIND_CSW_COUNTER: Used for requesting preemption performance
|
|
* counter save/restore buffer
|
|
*/
|
|
HFI_MEMKIND_CSW_COUNTER,
|
|
/**
|
|
* @HFI_MEMKIND_CTXTREC_PREEMPT_CNTR: Used for requesting preemption
|
|
* counter buffer
|
|
*/
|
|
HFI_MEMKIND_CTXTREC_PREEMPT_CNTR,
|
|
/** @HFI_MEMKIND_SYSLOG: Used for requesting system log memory */
|
|
HFI_MEMKIND_SYS_LOG,
|
|
/** @HFI_MEMKIND_CRASH_DUMP: Used for requesting carsh dumper memory */
|
|
HFI_MEMKIND_CRASH_DUMP,
|
|
/**
|
|
* @HFI_MEMKIND_MMIO_DPU: Used for requesting Display processing unit's
|
|
* register space
|
|
*/
|
|
HFI_MEMKIND_MMIO_DPU,
|
|
/**
|
|
* @HFI_MEMKIND_MMIO_TCSR: Used for requesting Top CSR(contains SoC
|
|
* doorbells) register space
|
|
*/
|
|
HFI_MEMKIND_MMIO_TCSR,
|
|
/**
|
|
* @HFI_MEMKIND_MMIO_QDSS_STM: Used for requesting QDSS STM register
|
|
* space
|
|
*/
|
|
HFI_MEMKIND_MMIO_QDSS_STM,
|
|
/** @HFI_MEMKIND_PROFILE: Used for kernel profiling */
|
|
HFI_MEMKIND_PROFILE,
|
|
/** @HFI_MEMKIND_USER_PROFILING_IBS: Used for user profiling */
|
|
HFI_MEMKIND_USER_PROFILE_IBS,
|
|
/** @MEMKIND_CMD_BUFFER: Used for composing ringbuffer content */
|
|
HFI_MEMKIND_CMD_BUFFER,
|
|
/**
|
|
* @HFI_MEMKIND_GPU_BUSY_DATA_BUFFER: Used for GPU busy buffer for
|
|
* all the contexts
|
|
*/
|
|
HFI_MEMKIND_GPU_BUSY_DATA_BUFFER,
|
|
/** @HFI_MEMKIND_GPU_BUSY_CMD_BUFFER: Used for GPU busy cmd buffer
|
|
* (Only readable to GPU)
|
|
*/
|
|
HFI_MEMKIND_GPU_BUSY_CMD_BUFFER,
|
|
/**
|
|
*@MEMKIND_MMIO_IPC_CORE: Used for IPC_core region mapping to GMU space
|
|
* for EVA to GPU communication.
|
|
*/
|
|
HFI_MEMKIND_MMIO_IPC_CORE,
|
|
/** @HFIMEMKIND_MMIO_IPCC_AOSS: Used for IPCC AOSS, second memory region */
|
|
HFI_MEMKIND_MMIO_IPCC_AOSS,
|
|
/**
|
|
* @MEMKIND_CSW_LPAC_PRIV_NON_SECURE: Used for privileged nonsecure
|
|
* memory for LPAC context record
|
|
*/
|
|
HFI_MEMKIND_CSW_LPAC_PRIV_NON_SECURE,
|
|
/** @HFI_MEMKIND_MEMSTORE: Buffer used to query a context's GPU sop/eop timestamps */
|
|
HFI_MEMKIND_MEMSTORE,
|
|
/** @HFI_MEMKIND_HW_FENCE: Hardware fence Tx/Rx headers and queues */
|
|
HFI_MEMKIND_HW_FENCE,
|
|
/** @HFI_MEMKIND_PREEMPT_SCRATCH: Used for Preemption scratch memory */
|
|
HFI_MEMKIND_PREEMPT_SCRATCH,
|
|
/**
|
|
* @HFI_MEMKIND_AQE_BUFFER: Sandbox memory used by AQE to switch
|
|
* between LPAC and GC
|
|
*/
|
|
HFI_MEMKIND_AQE_BUFFER,
|
|
HFI_MEMKIND_MAX,
|
|
};
|
|
|
|
static const char * const hfi_memkind_strings[] = {
|
|
[HFI_MEMKIND_GENERIC] = "GMU GENERIC",
|
|
[HFI_MEMKIND_RB] = "GMU RB",
|
|
[HFI_MEMKIND_SCRATCH] = "GMU SCRATCH",
|
|
[HFI_MEMKIND_CSW_SMMU_INFO] = "GMU SMMU INFO",
|
|
[HFI_MEMKIND_CSW_PRIV_NON_SECURE] = "GMU CSW PRIV NON SECURE",
|
|
[HFI_MEMKIND_CSW_PRIV_SECURE] = "GMU CSW PRIV SECURE",
|
|
[HFI_MEMKIND_CSW_NON_PRIV] = "GMU CSW NON PRIV",
|
|
[HFI_MEMKIND_CSW_COUNTER] = "GMU CSW COUNTER",
|
|
[HFI_MEMKIND_CTXTREC_PREEMPT_CNTR] = "GMU PREEMPT CNTR",
|
|
[HFI_MEMKIND_SYS_LOG] = "GMU SYS LOG",
|
|
[HFI_MEMKIND_CRASH_DUMP] = "GMU CRASHDUMP",
|
|
[HFI_MEMKIND_MMIO_DPU] = "GMU MMIO DPU",
|
|
[HFI_MEMKIND_MMIO_TCSR] = "GMU MMIO TCSR",
|
|
[HFI_MEMKIND_MMIO_QDSS_STM] = "GMU MMIO QDSS STM",
|
|
[HFI_MEMKIND_PROFILE] = "GMU KERNEL PROFILING",
|
|
[HFI_MEMKIND_USER_PROFILE_IBS] = "GMU USER PROFILING",
|
|
[HFI_MEMKIND_CMD_BUFFER] = "GMU CMD BUFFER",
|
|
[HFI_MEMKIND_GPU_BUSY_DATA_BUFFER] = "GMU BUSY DATA BUFFER",
|
|
[HFI_MEMKIND_GPU_BUSY_CMD_BUFFER] = "GMU BUSY CMD BUFFER",
|
|
[HFI_MEMKIND_MMIO_IPC_CORE] = "GMU MMIO IPC",
|
|
[HFI_MEMKIND_MMIO_IPCC_AOSS] = "GMU MMIO IPCC AOSS",
|
|
[HFI_MEMKIND_CSW_LPAC_PRIV_NON_SECURE] = "GMU CSW LPAC PRIV NON SECURE",
|
|
[HFI_MEMKIND_MEMSTORE] = "GMU MEMSTORE",
|
|
[HFI_MEMKIND_HW_FENCE] = "GMU HW FENCE",
|
|
[HFI_MEMKIND_PREEMPT_SCRATCH] = "GMU PREEMPTION",
|
|
[HFI_MEMKIND_AQE_BUFFER] = "GMU AQE BUFFER",
|
|
[HFI_MEMKIND_MAX] = "GMU UNKNOWN",
|
|
};
|
|
|
|
/* CP/GFX pipeline can access */
|
|
#define HFI_MEMFLAG_GFX_ACC BIT(0)
|
|
|
|
/* Buffer has APRIV protection in GFX PTEs */
|
|
#define HFI_MEMFLAG_GFX_PRIV BIT(1)
|
|
|
|
/* Buffer is read-write for GFX PTEs. A 0 indicates read-only */
|
|
#define HFI_MEMFLAG_GFX_WRITEABLE BIT(2)
|
|
|
|
/* GMU can access */
|
|
#define HFI_MEMFLAG_GMU_ACC BIT(3)
|
|
|
|
/* Buffer has APRIV protection in GMU PTEs */
|
|
#define HFI_MEMFLAG_GMU_PRIV BIT(4)
|
|
|
|
/* Buffer is read-write for GMU PTEs. A 0 indicates read-only */
|
|
#define HFI_MEMFLAG_GMU_WRITEABLE BIT(5)
|
|
|
|
/* Buffer is located in GMU's non-cached bufferable VA range */
|
|
#define HFI_MEMFLAG_GMU_BUFFERABLE BIT(6)
|
|
|
|
/* Buffer is located in GMU's cacheable VA range */
|
|
#define HFI_MEMFLAG_GMU_CACHEABLE BIT(7)
|
|
|
|
/* Host can access */
|
|
#define HFI_MEMFLAG_HOST_ACC BIT(8)
|
|
|
|
/* Host initializes(zero-init) the buffer */
|
|
#define HFI_MEMFLAG_HOST_INIT BIT(9)
|
|
|
|
/* Gfx buffer needs to be secure */
|
|
#define HFI_MEMFLAG_GFX_SECURE BIT(12)
|
|
|
|
/**
|
|
* struct hfi_queue_table_header - HFI queue table structure
|
|
* @version: HFI protocol version
|
|
* @size: queue table size in dwords
|
|
* @qhdr0_offset: first queue header offset (dwords) in this table
|
|
* @qhdr_size: queue header size
|
|
* @num_q: number of queues defined in this table
|
|
* @num_active_q: number of active queues
|
|
*/
|
|
struct hfi_queue_table_header {
|
|
u32 version;
|
|
u32 size;
|
|
u32 qhdr0_offset;
|
|
u32 qhdr_size;
|
|
u32 num_q;
|
|
u32 num_active_q;
|
|
} __packed;
|
|
|
|
/**
|
|
* struct gmu_context_queue_header - GMU context queue header structure
|
|
*/
|
|
struct gmu_context_queue_header {
|
|
/** @version: Version of the header */
|
|
u32 version;
|
|
/** @start_addr: GMU VA of start of the queue */
|
|
u32 start_addr;
|
|
/** @queue_size: queue size in dwords */
|
|
u32 queue_size;
|
|
/** @out_fence_ts: Timestamp of last hardware fence sent to Tx Queue */
|
|
volatile u32 out_fence_ts;
|
|
/** @sync_obj_ts: Timestamp of last sync object that GMU has digested */
|
|
volatile u32 sync_obj_ts;
|
|
/** @read_index: Read index of the queue */
|
|
volatile u32 read_index;
|
|
/** @write_index: Write index of the queue */
|
|
volatile u32 write_index;
|
|
/**
|
|
* @hw_fence_buffer_va: GMU VA of the buffer to store output hardware fences for this
|
|
* context
|
|
*/
|
|
u32 hw_fence_buffer_va;
|
|
/**
|
|
* @hw_fence_buffer_size: Size of the buffer to store output hardware fences for this
|
|
* context
|
|
*/
|
|
u32 hw_fence_buffer_size;
|
|
u32 unused1;
|
|
u32 unused2;
|
|
u32 unused3;
|
|
} __packed;
|
|
|
|
/**
|
|
* struct hfi_queue_header - HFI queue header structure
|
|
* @status: active: 1; inactive: 0
|
|
* @start_addr: starting address of the queue in GMU VA space
|
|
* @type: queue type encoded the priority, ID and send/recevie types
|
|
* @queue_size: size of the queue
|
|
* @msg_size: size of the message if each message has fixed size.
|
|
* Otherwise, 0 means variable size of message in the queue.
|
|
* @read_index: read index of the queue
|
|
* @write_index: write index of the queue
|
|
*/
|
|
struct hfi_queue_header {
|
|
u32 status;
|
|
u32 start_addr;
|
|
u32 type;
|
|
u32 queue_size;
|
|
u32 msg_size;
|
|
u32 unused0;
|
|
u32 unused1;
|
|
u32 unused2;
|
|
u32 unused3;
|
|
u32 unused4;
|
|
volatile u32 read_index;
|
|
volatile u32 write_index;
|
|
} __packed;
|
|
|
|
#define HFI_MSG_CMD 0 /* V1 and V2 */
|
|
#define HFI_MSG_ACK 1 /* V2 only */
|
|
|
|
/* Used to NOP a command when executing warmboot sequence */
|
|
#define HFI_MSG_NOP BIT(18)
|
|
/* Used to record a command when executing coldboot sequence */
|
|
#define HFI_MSG_RECORD BIT(19)
|
|
|
|
#define HFI_V1_MSG_POST 1 /* V1 only */
|
|
#define HFI_V1_MSG_ACK 2/* V1 only */
|
|
|
|
#define MSG_HDR_SET_SIZE(hdr, size) \
|
|
(((size & 0xFF) << 8) | hdr)
|
|
|
|
#define CREATE_MSG_HDR(id, type) \
|
|
(((type) << 16) | ((id) & 0xFF))
|
|
|
|
#define ACK_MSG_HDR(id) CREATE_MSG_HDR(id, HFI_MSG_ACK)
|
|
|
|
#define HFI_QUEUE_DEFAULT_CNT 3
|
|
#define HFI_QUEUE_DISPATCH_MAX_CNT 14
|
|
#define HFI_QUEUE_HDR_MAX (HFI_QUEUE_DEFAULT_CNT + HFI_QUEUE_DISPATCH_MAX_CNT)
|
|
|
|
struct hfi_queue_table {
|
|
struct hfi_queue_table_header qtbl_hdr;
|
|
struct hfi_queue_header qhdr[HFI_QUEUE_HDR_MAX];
|
|
} __packed;
|
|
|
|
#define HFI_QUEUE_OFFSET(i) \
|
|
(ALIGN(sizeof(struct hfi_queue_table), SZ_16) + \
|
|
((i) * HFI_QUEUE_SIZE))
|
|
|
|
#define GMU_QUEUE_START_ADDR(gmuaddr, i) \
|
|
(gmuaddr + HFI_QUEUE_OFFSET(i))
|
|
|
|
#define HOST_QUEUE_START_ADDR(hfi_mem, i) \
|
|
((hfi_mem)->hostptr + HFI_QUEUE_OFFSET(i))
|
|
|
|
#define MSG_HDR_GET_ID(hdr) ((hdr) & 0xFF)
|
|
#define MSG_HDR_GET_SIZE(hdr) (((hdr) >> 8) & 0xFF)
|
|
#define MSG_HDR_GET_TYPE(hdr) (((hdr) >> 16) & 0xF)
|
|
#define MSG_HDR_GET_SEQNUM(hdr) (((hdr) >> 20) & 0xFFF)
|
|
|
|
/* Clear the HFI_MSG_RECORD bit from both headers since some acks may have it set, and some not. */
|
|
#define CMP_HFI_ACK_HDR(sent, rcvd) ((sent &= ~HFI_MSG_RECORD) == (rcvd &= ~HFI_MSG_RECORD))
|
|
|
|
#define MSG_HDR_SET_SEQNUM(hdr, num) \
|
|
(((hdr) & 0xFFFFF) | ((num) << 20))
|
|
|
|
#define MSG_HDR_SET_SEQNUM_SIZE(hdr, seqnum, sizedwords) \
|
|
(FIELD_PREP(GENMASK(31, 20), seqnum) | FIELD_PREP(GENMASK(15, 8), sizedwords) | hdr)
|
|
|
|
#define MSG_HDR_SET_TYPE(hdr, type) \
|
|
(((hdr) & 0xFFFFF) | ((type) << 16))
|
|
|
|
#define QUEUE_HDR_TYPE(id, prio, rtype, stype) \
|
|
(((id) & 0xFF) | (((prio) & 0xFF) << 8) | \
|
|
(((rtype) & 0xFF) << 16) | (((stype) & 0xFF) << 24))
|
|
|
|
#define HFI_RSP_TIMEOUT 1000 /* msec */
|
|
|
|
#define HFI_IRQ_MSGQ_MASK BIT(0)
|
|
|
|
enum hfi_msg_type {
|
|
H2F_MSG_INIT = 0,
|
|
H2F_MSG_FW_VER = 1,
|
|
H2F_MSG_LM_CFG = 2,
|
|
H2F_MSG_BW_VOTE_TBL = 3,
|
|
H2F_MSG_PERF_TBL = 4,
|
|
H2F_MSG_TEST = 5,
|
|
H2F_MSG_ACD_TBL = 7,
|
|
H2F_MSG_CLX_TBL = 8,
|
|
H2F_MSG_START = 10,
|
|
H2F_MSG_FEATURE_CTRL = 11,
|
|
H2F_MSG_GET_VALUE = 12,
|
|
H2F_MSG_SET_VALUE = 13,
|
|
H2F_MSG_CORE_FW_START = 14,
|
|
H2F_MSG_TABLE = 15,
|
|
F2H_MSG_MEM_ALLOC = 20,
|
|
H2F_MSG_GX_BW_PERF_VOTE = 30,
|
|
H2F_MSG_FW_HALT = 32,
|
|
H2F_MSG_PREPARE_SLUMBER = 33,
|
|
F2H_MSG_ERR = 100,
|
|
F2H_MSG_DEBUG = 101,
|
|
F2H_MSG_LOG_BLOCK = 102,
|
|
F2H_MSG_GMU_CNTR_REGISTER = 110,
|
|
F2H_MSG_GMU_CNTR_RELEASE = 111,
|
|
F2H_MSG_ACK = 126, /* Deprecated for v2.0*/
|
|
H2F_MSG_ACK = 127, /* Deprecated for v2.0*/
|
|
H2F_MSG_REGISTER_CONTEXT = 128,
|
|
H2F_MSG_UNREGISTER_CONTEXT = 129,
|
|
H2F_MSG_ISSUE_CMD = 130,
|
|
H2F_MSG_ISSUE_CMD_RAW = 131,
|
|
H2F_MSG_TS_NOTIFY = 132,
|
|
F2H_MSG_TS_RETIRE = 133,
|
|
H2F_MSG_CONTEXT_POINTERS = 134,
|
|
H2F_MSG_ISSUE_LPAC_CMD_RAW = 135,
|
|
H2F_MSG_CONTEXT_RULE = 140, /* AKA constraint */
|
|
H2F_MSG_ISSUE_RECURRING_CMD = 141,
|
|
F2H_MSG_CONTEXT_BAD = 150,
|
|
H2F_MSG_HW_FENCE_INFO = 151,
|
|
H2F_MSG_ISSUE_SYNCOBJ = 152,
|
|
F2H_MSG_SYNCOBJ_QUERY = 153,
|
|
H2F_MSG_WARMBOOT_CMD = 154,
|
|
F2H_MSG_PROCESS_TRACE = 155,
|
|
HFI_MAX_ID,
|
|
};
|
|
|
|
enum gmu_ret_type {
|
|
GMU_SUCCESS = 0,
|
|
GMU_ERROR_FATAL,
|
|
GMU_ERROR_MEM_FAIL,
|
|
GMU_ERROR_INVAL_PARAM,
|
|
GMU_ERROR_NULL_PTR,
|
|
GMU_ERROR_OUT_OF_BOUNDS,
|
|
GMU_ERROR_TIMEOUT,
|
|
GMU_ERROR_NOT_SUPPORTED,
|
|
GMU_ERROR_NO_ENTRY,
|
|
};
|
|
|
|
/* H2F */
|
|
struct hfi_gmu_init_cmd {
|
|
u32 hdr;
|
|
u32 seg_id;
|
|
u32 dbg_buffer_addr;
|
|
u32 dbg_buffer_size;
|
|
u32 boot_state;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_fw_version_cmd {
|
|
u32 hdr;
|
|
u32 supported_ver;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_bwtable_cmd {
|
|
u32 hdr;
|
|
u32 bw_level_num;
|
|
u32 cnoc_cmds_num;
|
|
u32 ddr_cmds_num;
|
|
u32 cnoc_wait_bitmask;
|
|
u32 ddr_wait_bitmask;
|
|
u32 cnoc_cmd_addrs[MAX_CNOC_CMDS];
|
|
u32 cnoc_cmd_data[MAX_CNOC_LEVELS][MAX_CNOC_CMDS];
|
|
u32 ddr_cmd_addrs[MAX_BW_CMDS];
|
|
u32 ddr_cmd_data[MAX_BW_LEVELS][MAX_BW_CMDS];
|
|
} __packed;
|
|
|
|
struct opp_gx_desc {
|
|
u32 vote;
|
|
/* This is 'acdLvl' in gmu fw which is now repurposed for cx vote */
|
|
u32 cx_vote;
|
|
u32 freq;
|
|
} __packed;
|
|
|
|
struct opp_desc {
|
|
u32 vote;
|
|
u32 freq;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_dcvstable_v1_cmd {
|
|
u32 hdr;
|
|
u32 gpu_level_num;
|
|
u32 gmu_level_num;
|
|
struct opp_desc gx_votes[MAX_GX_LEVELS_LEGACY];
|
|
struct opp_desc cx_votes[MAX_CX_LEVELS];
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_dcvstable_cmd {
|
|
u32 hdr;
|
|
u32 gpu_level_num;
|
|
u32 gmu_level_num;
|
|
struct opp_gx_desc gx_votes[MAX_GX_LEVELS_LEGACY];
|
|
struct opp_desc cx_votes[MAX_CX_LEVELS];
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_table_entry {
|
|
u32 count;
|
|
u32 stride;
|
|
u32 data[];
|
|
} __packed;
|
|
|
|
struct hfi_table_cmd {
|
|
u32 hdr;
|
|
u32 version;
|
|
u32 type;
|
|
struct hfi_table_entry entry[];
|
|
} __packed;
|
|
|
|
#define MAX_ACD_STRIDE 2
|
|
#define MAX_ACD_NUM_LEVELS KGSL_MAX_PWRLEVELS
|
|
|
|
/* H2F */
|
|
struct hfi_acd_table_cmd {
|
|
u32 hdr;
|
|
u32 version;
|
|
u32 enable_by_level;
|
|
u32 stride;
|
|
u32 num_levels;
|
|
u32 data[MAX_ACD_NUM_LEVELS * MAX_ACD_STRIDE];
|
|
} __packed;
|
|
|
|
struct hfi_clx_table_v1_cmd {
|
|
/** @hdr: HFI header message */
|
|
u32 hdr;
|
|
/**
|
|
* @data0: bits[0:15] Feature enable control
|
|
* bits[16:31] Revision control
|
|
*/
|
|
u32 data0;
|
|
/**
|
|
* @data1: bits[0:15] Migration time
|
|
* bits[16:21] Current rating
|
|
* bits[22:27] Phases for domain
|
|
* bits[28:28] Path notifications
|
|
* bits[29:31] Extra feature bits
|
|
*/
|
|
u32 data1;
|
|
/** @clxt: CLX time in microseconds */
|
|
u32 clxt;
|
|
/** @clxh: CLH time in microseconds */
|
|
u32 clxh;
|
|
/** @urgmode: Urgent HW throttle mode of operation */
|
|
u32 urgmode;
|
|
/** @lkgen: Enable leakage current estimate */
|
|
u32 lkgen;
|
|
} __packed;
|
|
|
|
#define CLX_DOMAINS_V2 2
|
|
struct clx_domain_v2 {
|
|
/**
|
|
* @data0: bits[0:15] Migration time
|
|
* bits[16:21] Current rating
|
|
* bits[22:27] Phases for domain
|
|
* bits[28:28] Path notifications
|
|
* bits[29:31] Extra feature bits
|
|
*/
|
|
u32 data0;
|
|
/** @clxt: CLX time in microseconds */
|
|
u32 clxt;
|
|
/** @clxh: CLH time in microseconds */
|
|
u32 clxh;
|
|
/** @urgmode: Urgent HW throttle mode of operation */
|
|
u32 urgmode;
|
|
/** @lkgen: Enable leakage current estimate */
|
|
u32 lkgen;
|
|
/** @currbudget: Current Budget */
|
|
u32 currbudget;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_clx_table_v2_cmd {
|
|
/** @hdr: HFI header message */
|
|
u32 hdr;
|
|
/** @version: Version identifier for the format used for domains */
|
|
u32 version;
|
|
/** @domain: GFX and MXC Domain information */
|
|
struct clx_domain_v2 domain[CLX_DOMAINS_V2];
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_test_cmd {
|
|
u32 hdr;
|
|
u32 data;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_start_cmd {
|
|
u32 hdr;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_feature_ctrl_cmd {
|
|
u32 hdr;
|
|
u32 feature;
|
|
u32 enable;
|
|
u32 data;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_get_value_cmd {
|
|
u32 hdr;
|
|
u32 type;
|
|
u32 subtype;
|
|
} __packed;
|
|
|
|
/* Internal */
|
|
struct hfi_get_value_req {
|
|
struct hfi_get_value_cmd cmd;
|
|
u32 data[16];
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_get_value_reply_cmd {
|
|
u32 hdr;
|
|
u32 req_hdr;
|
|
u32 data[16];
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_set_value_cmd {
|
|
u32 hdr;
|
|
u32 type;
|
|
u32 subtype;
|
|
u32 data;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_core_fw_start_cmd {
|
|
u32 hdr;
|
|
u32 handle;
|
|
} __packed;
|
|
|
|
struct hfi_mem_alloc_desc_legacy {
|
|
u64 gpu_addr;
|
|
u32 flags;
|
|
u32 mem_kind;
|
|
u32 host_mem_handle;
|
|
u32 gmu_mem_handle;
|
|
u32 gmu_addr;
|
|
u32 size; /* Bytes */
|
|
} __packed;
|
|
|
|
struct hfi_mem_alloc_desc {
|
|
u64 gpu_addr;
|
|
u32 flags;
|
|
u32 mem_kind;
|
|
u32 host_mem_handle;
|
|
u32 gmu_mem_handle;
|
|
u32 gmu_addr;
|
|
u32 size; /* Bytes */
|
|
/**
|
|
* @align: bits[0:7] specify alignment requirement of the GMU VA specified as a power of
|
|
* two. bits[8:15] specify alignment requirement for the size of the GMU mapping. For
|
|
* example, a decimal value of 20 = (1 << 20) = 1 MB alignment
|
|
*/
|
|
u32 align;
|
|
} __packed;
|
|
|
|
struct hfi_mem_alloc_entry {
|
|
struct hfi_mem_alloc_desc desc;
|
|
struct kgsl_memdesc *md;
|
|
};
|
|
|
|
/* F2H */
|
|
struct hfi_mem_alloc_cmd_legacy {
|
|
u32 hdr;
|
|
u32 reserved; /* Padding to ensure alignment of 'desc' below */
|
|
struct hfi_mem_alloc_desc_legacy desc;
|
|
} __packed;
|
|
|
|
struct hfi_mem_alloc_cmd {
|
|
u32 hdr;
|
|
u32 version;
|
|
struct hfi_mem_alloc_desc desc;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_mem_alloc_reply_cmd {
|
|
u32 hdr;
|
|
u32 req_hdr;
|
|
struct hfi_mem_alloc_desc desc;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_gx_bw_perf_vote_cmd {
|
|
u32 hdr;
|
|
u32 ack_type;
|
|
u32 freq;
|
|
u32 bw;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_fw_halt_cmd {
|
|
u32 hdr;
|
|
u32 en_halt;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_prep_slumber_cmd {
|
|
u32 hdr;
|
|
u32 bw;
|
|
u32 freq;
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_err_cmd {
|
|
u32 hdr;
|
|
u32 error_code;
|
|
u32 data[16];
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_debug_cmd {
|
|
u32 hdr;
|
|
u32 type;
|
|
u32 timestamp;
|
|
u32 data;
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_trace_cmd {
|
|
u32 hdr;
|
|
u32 version;
|
|
u64 identifier;
|
|
} __packed;
|
|
|
|
/* Trace packet definition */
|
|
struct gmu_trace_packet {
|
|
u32 hdr;
|
|
u32 trace_id;
|
|
u64 ticks;
|
|
u32 payload[];
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_gmu_cntr_register_cmd {
|
|
u32 hdr;
|
|
u32 group_id;
|
|
u32 countable;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_gmu_cntr_register_reply_cmd {
|
|
u32 hdr;
|
|
u32 req_hdr;
|
|
u32 group_id;
|
|
u32 countable;
|
|
u32 cntr_lo;
|
|
u32 cntr_hi;
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_gmu_cntr_release_cmd {
|
|
u32 hdr;
|
|
u32 group_id;
|
|
u32 countable;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_register_ctxt_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 flags;
|
|
u64 pt_addr;
|
|
u32 ctxt_idr;
|
|
u32 ctxt_bank;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_unregister_ctxt_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 ts;
|
|
} __packed;
|
|
|
|
struct hfi_issue_ib {
|
|
u64 addr;
|
|
u32 size;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
/* The length of *buf will be embedded in the hdr */
|
|
struct hfi_issue_cmd_raw_cmd {
|
|
u32 hdr;
|
|
u32 *buf;
|
|
} __packed;
|
|
|
|
/* Internal */
|
|
struct hfi_issue_cmd_raw_req {
|
|
u32 queue;
|
|
u32 ctxt_id;
|
|
u32 len;
|
|
u32 *buf;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_ts_notify_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 ts;
|
|
} __packed;
|
|
|
|
#define CMDBATCH_SUCCESS 0
|
|
#define CMDBATCH_RETIRED 1
|
|
#define CMDBATCH_ERROR 2
|
|
#define CMDBATCH_SKIP 3
|
|
|
|
#define CMDBATCH_PROFILING BIT(4)
|
|
#define CMDBATCH_EOF BIT(8)
|
|
#define CMDBATCH_INDIRECT BIT(9)
|
|
#define CMDBATCH_RECURRING_START BIT(18)
|
|
#define CMDBATCH_RECURRING_STOP BIT(19)
|
|
|
|
|
|
/* This indicates that the SYNCOBJ is kgsl output fence */
|
|
#define GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT 0
|
|
/* This indicates that the SYNCOBJ is signaled */
|
|
#define GMU_SYNCOBJ_FLAG_SIGNALED_BIT 1
|
|
/* This indicates that the SYNCOBJ's software status is queried */
|
|
#define GMU_SYNCOBJ_FLAG_QUERY_SW_STATUS_BIT 2
|
|
/* This indicates that the SYNCOBJ's software status is signaled */
|
|
#define GMU_SYNCOBJ_FLAG_SW_STATUS_SIGNALED_BIT 3
|
|
/* This indicates that the SYNCOBJ's software status is pending */
|
|
#define GMU_SYNCOBJ_FLAG_SW_STATUS_PENDING_BIT 4
|
|
|
|
#define GMU_SYNCOBJ_FLAGS \
|
|
{ BIT(GMU_SYNCOBJ_FLAG_KGSL_FENCE_BIT), "KGSL"}, \
|
|
{ BIT(GMU_SYNCOBJ_FLAG_SIGNALED_BIT), "SIGNALED"}, \
|
|
{ BIT(GMU_SYNCOBJ_FLAG_QUERY_SW_STATUS_BIT), "QUERIED"}, \
|
|
{ BIT(GMU_SYNCOBJ_FLAG_SW_STATUS_SIGNALED_BIT), "SW_SIGNALED"}, \
|
|
{ BIT(GMU_SYNCOBJ_FLAG_SW_STATUS_PENDING_BIT), "SW_PENDING"}
|
|
|
|
/* F2H */
|
|
struct hfi_ts_retire_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 ts;
|
|
u32 type;
|
|
u64 submitted_to_rb;
|
|
u64 sop;
|
|
u64 eop;
|
|
u64 retired_on_gmu;
|
|
u64 active;
|
|
u32 version;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_context_pointers_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u64 sop_addr;
|
|
u64 eop_addr;
|
|
u64 user_ctxt_record_addr;
|
|
u32 version;
|
|
u32 gmu_context_queue_addr;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_context_rule_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 type;
|
|
u32 status;
|
|
} __packed;
|
|
|
|
struct fault_info {
|
|
u32 ctxt_id;
|
|
u32 policy;
|
|
u32 ts;
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_context_bad_cmd {
|
|
u32 hdr;
|
|
u32 version;
|
|
struct fault_info gc;
|
|
struct fault_info lpac;
|
|
u32 error;
|
|
u32 payload[];
|
|
} __packed;
|
|
|
|
/* F2H */
|
|
struct hfi_context_bad_cmd_legacy {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 policy;
|
|
u32 ts;
|
|
u32 error;
|
|
u32 payload[];
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_context_bad_reply_cmd {
|
|
u32 hdr;
|
|
u32 req_hdr;
|
|
} __packed;
|
|
|
|
/* H2F */
|
|
struct hfi_submit_cmd {
|
|
u32 hdr;
|
|
u32 ctxt_id;
|
|
u32 flags;
|
|
u32 ts;
|
|
u32 profile_gpuaddr_lo;
|
|
u32 profile_gpuaddr_hi;
|
|
u32 numibs;
|
|
u32 big_ib_gmu_va;
|
|
} __packed;
|
|
|
|
struct hfi_syncobj {
|
|
u64 ctxt_id;
|
|
u64 seq_no;
|
|
u64 flags;
|
|
} __packed;
|
|
|
|
struct hfi_submit_syncobj {
|
|
u32 hdr;
|
|
u32 version;
|
|
u32 flags;
|
|
u32 timestamp;
|
|
u32 num_syncobj;
|
|
} __packed;
|
|
|
|
struct hfi_log_block {
|
|
u32 hdr;
|
|
u32 version;
|
|
u32 start_index;
|
|
u32 stop_index;
|
|
} __packed;
|
|
|
|
enum hfi_warmboot_cmd_type {
|
|
HFI_WARMBOOT_SET_SCRATCH = 0,
|
|
HFI_WARMBOOT_EXEC_SCRATCH,
|
|
HFI_WARMBOOT_QUERY_SCRATCH,
|
|
};
|
|
|
|
struct hfi_warmboot_scratch_cmd {
|
|
/** @hdr: Header for the scratch command packet */
|
|
u32 hdr;
|
|
/** @version: Version of the scratch command packet */
|
|
u32 version;
|
|
/** @flags: Set, Execute or Query scratch flag */
|
|
u32 flags;
|
|
/** @scratch_addr: Address of the scratch */
|
|
u32 scratch_addr;
|
|
/** @scratch_size: Size of the scratch in bytes*/
|
|
u32 scratch_size;
|
|
} __packed;
|
|
|
|
/* Request GMU to add this fence to TxQueue without checking whether this is retired or not */
|
|
#define HW_FENCE_FLAG_SKIP_MEMSTORE 0x1
|
|
|
|
struct hfi_hw_fence_info {
|
|
/** @hdr: Header for the fence info packet */
|
|
u32 hdr;
|
|
/** @version: Version of the fence info packet */
|
|
u32 version;
|
|
/** @gmu_ctxt_id: GMU Context id to which this fence belongs */
|
|
u32 gmu_ctxt_id;
|
|
/** @error: Any error code associated with this fence */
|
|
u32 error;
|
|
/** @ctxt_id: Context id for which hw fence is to be triggered */
|
|
u64 ctxt_id;
|
|
/** @ts: Timestamp for which hw fence is to be triggered */
|
|
u64 ts;
|
|
/** @flags: Flags on how to handle this hfi packet */
|
|
u64 flags;
|
|
/** @hash_index: Index of the hw fence in hw fence table */
|
|
u64 hash_index;
|
|
} __packed;
|
|
|
|
/* The software fence corresponding to the queried hardware fence has not signaled */
|
|
#define ADRENO_HW_FENCE_SW_STATUS_PENDING BIT(0)
|
|
/* The software fence corresponding to the queried hardware fence has signaled */
|
|
#define ADRENO_HW_FENCE_SW_STATUS_SIGNALED BIT(1)
|
|
|
|
struct hfi_syncobj_query {
|
|
/**
|
|
* @query_bitmask: Bitmask representing the sync object descriptors to be queried. For
|
|
* example, to query the second sync object descriptor(index=1) in a sync object,
|
|
* bit(1) should be set in this bitmask.
|
|
*/
|
|
u32 query_bitmask;
|
|
} __packed;
|
|
|
|
#define MAX_SYNCOBJ_QUERY_BITS 128
|
|
#define BITS_PER_SYNCOBJ_QUERY 32
|
|
#define MAX_SYNCOBJ_QUERY_DWORDS (MAX_SYNCOBJ_QUERY_BITS / BITS_PER_SYNCOBJ_QUERY)
|
|
|
|
struct hfi_syncobj_query_cmd {
|
|
/** @hdr: Header for the fence info packet */
|
|
u32 hdr;
|
|
/** @version: Version of the fence info packet */
|
|
u32 version;
|
|
/** @gmu_ctxt_id: GMU Context id to which this SYNC object belongs */
|
|
u32 gmu_ctxt_id;
|
|
/** @sync_obj_ts: Timestamp of this SYNC object */
|
|
u32 sync_obj_ts;
|
|
/** @queries: Array of query bitmasks */
|
|
struct hfi_syncobj_query queries[MAX_SYNCOBJ_QUERY_DWORDS];
|
|
} __packed;
|
|
|
|
/**
|
|
* struct pending_cmd - data structure to track outstanding HFI
|
|
* command messages
|
|
*/
|
|
struct pending_cmd {
|
|
/** @sent_hdr: Header of the un-ack'd hfi packet */
|
|
u32 sent_hdr;
|
|
/** @results: Array to store the ack packet */
|
|
u32 results[MAX_RCVD_SIZE];
|
|
/** @complete: Completion to signal hfi ack has been received */
|
|
struct completion complete;
|
|
/** @node: to add it to the list of hfi packets waiting for ack */
|
|
struct list_head node;
|
|
};
|
|
|
|
static inline int _CMD_MSG_HDR(u32 *hdr, int id, size_t size)
|
|
{
|
|
if (WARN_ON(size > HFI_MAX_MSG_SIZE))
|
|
return -EMSGSIZE;
|
|
|
|
*hdr = CREATE_MSG_HDR(id, HFI_MSG_CMD);
|
|
return 0;
|
|
}
|
|
|
|
#define CMD_MSG_HDR(cmd, id) \
|
|
_CMD_MSG_HDR(&(cmd).hdr, id, sizeof(cmd))
|
|
|
|
#define RECORD_MSG_HDR(hdr) \
|
|
((hdr) | HFI_MSG_RECORD)
|
|
|
|
#define CLEAR_RECORD_MSG_HDR(hdr) \
|
|
((hdr) & (~(HFI_MSG_RECORD | HFI_MSG_NOP)))
|
|
|
|
#define RECORD_NOP_MSG_HDR(hdr) \
|
|
((hdr) | (HFI_MSG_RECORD | HFI_MSG_NOP))
|
|
|
|
/* Maximum number of IBs in a submission */
|
|
#define HWSCHED_MAX_DISPATCH_NUMIBS \
|
|
((HFI_MAX_MSG_SIZE - sizeof(struct hfi_submit_cmd)) \
|
|
/ sizeof(struct hfi_issue_ib))
|
|
|
|
/**
|
|
* struct payload_section - Container of keys values
|
|
*
|
|
* There may be a variable number of payload sections appended
|
|
* to the context bad HFI message. Each payload section contains
|
|
* a variable number of key-value pairs, both key and value being
|
|
* single dword each.
|
|
*/
|
|
struct payload_section {
|
|
/** @type: Type of the payload */
|
|
u16 type;
|
|
/** @dwords: Number of dwords in the data array. */
|
|
u16 dwords;
|
|
/** @data: A sequence of key-value pairs. Each pair is 2 dwords. */
|
|
u32 data[];
|
|
} __packed;
|
|
|
|
/* IDs for context bad hfi payloads */
|
|
#define PAYLOAD_FAULT_REGS 1
|
|
#define PAYLOAD_RB 2
|
|
#define PAYLOAD_PREEMPT_TIMEOUT 3
|
|
|
|
/* Keys for PAYLOAD_FAULT_REGS type payload */
|
|
#define KEY_CP_OPCODE_ERROR 1
|
|
#define KEY_CP_PROTECTED_ERROR 2
|
|
#define KEY_CP_HW_FAULT 3
|
|
#define KEY_CP_BV_OPCODE_ERROR 4
|
|
#define KEY_CP_BV_PROTECTED_ERROR 5
|
|
#define KEY_CP_BV_HW_FAULT 6
|
|
#define KEY_CP_LPAC_OPCODE_ERROR 7
|
|
#define KEY_CP_LPAC_PROTECTED_ERROR 8
|
|
#define KEY_CP_LPAC_HW_FAULT 9
|
|
#define KEY_SWFUSE_VIOLATION_FAULT 10
|
|
#define KEY_AQE0_OPCODE_ERROR 11
|
|
#define KEY_AQE0_HW_FAULT 12
|
|
#define KEY_AQE1_OPCODE_ERROR 13
|
|
#define KEY_AQE1_HW_FAULT 14
|
|
#define KEY_CP_AHB_ERROR 30
|
|
#define KEY_TSB_WRITE_ERROR 31
|
|
|
|
/* Keys for PAYLOAD_RB type payload */
|
|
#define KEY_RB_ID 1
|
|
#define KEY_RB_RPTR 2
|
|
#define KEY_RB_WPTR 3
|
|
#define KEY_RB_SIZEDWORDS 4
|
|
#define KEY_RB_QUEUED_TS 5
|
|
#define KEY_RB_RETIRED_TS 6
|
|
#define KEY_RB_GPUADDR_LO 7
|
|
#define KEY_RB_GPUADDR_HI 8
|
|
|
|
/* Keys for PAYLOAD_PREEMPT_TIMEOUT type payload */
|
|
#define KEY_PREEMPT_TIMEOUT_CUR_RB_ID 1
|
|
#define KEY_PREEMPT_TIMEOUT_NEXT_RB_ID 2
|
|
|
|
/* Types of errors that trigger context bad HFI */
|
|
|
|
/* GPU encountered a CP HW error */
|
|
#define GMU_CP_HW_ERROR 600
|
|
/* GPU encountered a GPU Hang interrupt */
|
|
#define GMU_GPU_HW_HANG 601
|
|
/* Preemption didn't complete in given time */
|
|
#define GMU_GPU_PREEMPT_TIMEOUT 602
|
|
/* Fault due to Long IB timeout */
|
|
#define GMU_GPU_SW_HANG 603
|
|
/* GPU encountered a bad opcode */
|
|
#define GMU_CP_OPCODE_ERROR 604
|
|
/* GPU encountered protected mode error */
|
|
#define GMU_CP_PROTECTED_ERROR 605
|
|
/* GPU encountered an illegal instruction */
|
|
#define GMU_CP_ILLEGAL_INST_ERROR 606
|
|
/* GPU encountered a CP ucode error */
|
|
#define GMU_CP_UCODE_ERROR 607
|
|
/* GPU encountered a CP hw fault error */
|
|
#define GMU_CP_HW_FAULT_ERROR 608
|
|
/* GPU encountered a GPC error */
|
|
#define GMU_CP_GPC_ERROR 609
|
|
/* GPU BV encountered a bad opcode */
|
|
#define GMU_CP_BV_OPCODE_ERROR 610
|
|
/* GPU BV encountered protected mode error */
|
|
#define GMU_CP_BV_PROTECTED_ERROR 611
|
|
/* GPU BV encountered a CP hw fault error */
|
|
#define GMU_CP_BV_HW_FAULT_ERROR 612
|
|
/* GPU BV encountered a CP ucode error */
|
|
#define GMU_CP_BV_UCODE_ERROR 613
|
|
/* GPU BV encountered an illegal instruction */
|
|
#define GMU_CP_BV_ILLEGAL_INST_ERROR 614
|
|
/* GPU encountered a bad LPAC opcode */
|
|
#define GMU_CP_LPAC_OPCODE_ERROR 615
|
|
/* GPU LPAC encountered a CP ucode error */
|
|
#define GMU_CP_LPAC_UCODE_ERROR 616
|
|
/* GPU LPAC encountered a CP hw fault error */
|
|
#define GMU_CP_LPAC_HW_FAULT_ERROR 617
|
|
/* GPU LPAC encountered protected mode error */
|
|
#define GMU_CP_LPAC_PROTECTED_ERROR 618
|
|
/* GPU LPAC encountered an illegal instruction */
|
|
#define GMU_CP_LPAC_ILLEGAL_INST_ERROR 619
|
|
/* Fault due to LPAC Long IB timeout */
|
|
#define GMU_GPU_LPAC_SW_HANG 620
|
|
/* Fault due to software fuse violation interrupt */
|
|
#define GMU_GPU_SW_FUSE_VIOLATION 621
|
|
/* AQE related error codes */
|
|
#define GMU_GPU_AQE0_OPCODE_ERRROR 622
|
|
#define GMU_GPU_AQE0_UCODE_ERROR 623
|
|
#define GMU_GPU_AQE0_HW_FAULT_ERROR 624
|
|
#define GMU_GPU_AQE0_ILLEGAL_INST_ERROR 625
|
|
#define GMU_GPU_AQE1_OPCODE_ERRROR 626
|
|
#define GMU_GPU_AQE1_UCODE_ERROR 627
|
|
#define GMU_GPU_AQE1_HW_FAULT_ERROR 628
|
|
#define GMU_GPU_AQE1_ILLEGAL_INST_ERROR 629
|
|
/* GMU encountered a sync object which is signaled via software but not via hardware */
|
|
#define GMU_SYNCOBJ_TIMEOUT_ERROR 630
|
|
/* Non fatal GPU error codes */
|
|
#define GMU_CP_AHB_ERROR 650
|
|
#define GMU_ATB_ASYNC_FIFO_OVERFLOW 651
|
|
#define GMU_RBBM_ATB_BUF_OVERFLOW 652
|
|
#define GMU_UCHE_OOB_ACCESS 653
|
|
#define GMU_UCHE_TRAP_INTR 654
|
|
#define GMU_TSB_WRITE_ERROR 655
|
|
|
|
/* GPU encountered an unknown CP error */
|
|
#define GMU_CP_UNKNOWN_ERROR 700
|
|
|
|
/**
|
|
* hfi_update_read_idx - Update the read index of an hfi queue
|
|
* hdr: Pointer to the hfi queue header
|
|
* index: New read index
|
|
*
|
|
* This function makes sure that kgsl has consumed f2h packets
|
|
* before GMU sees the updated read index. This avoids a corner
|
|
* case where GMU might over-write f2h packets that have not yet
|
|
* been consumed by kgsl.
|
|
*/
|
|
static inline void hfi_update_read_idx(struct hfi_queue_header *hdr, u32 index)
|
|
{
|
|
/*
|
|
* This is to make sure packets are consumed before gmu sees the updated
|
|
* read index
|
|
*/
|
|
mb();
|
|
|
|
hdr->read_index = index;
|
|
}
|
|
|
|
/**
|
|
* hfi_update_write_idx - Update the write index of a GMU queue
|
|
* write_idx: Pointer to the write index
|
|
* index: New write index
|
|
*
|
|
* This function makes sure that the h2f packets are written out
|
|
* to memory before GMU sees the updated write index. This avoids
|
|
* corner cases where GMU might fetch stale entries that can happen
|
|
* if write index is updated before new packets have been written
|
|
* out to memory.
|
|
*/
|
|
static inline void hfi_update_write_idx(volatile u32 *write_idx, u32 index)
|
|
{
|
|
/*
|
|
* This is to make sure packets are written out before gmu sees the
|
|
* updated write index
|
|
*/
|
|
wmb();
|
|
|
|
*write_idx = index;
|
|
|
|
/*
|
|
* Memory barrier to make sure write index is written before an
|
|
* interrupt is raised
|
|
*/
|
|
wmb();
|
|
}
|
|
|
|
/**
|
|
* hfi_get_mem_alloc_desc - Get the descriptor from F2H_MSG_MEM_ALLOC packet
|
|
* rcvd: Pointer to the F2H_MSG_MEM_ALLOC packet
|
|
* out: Pointer to copy the descriptor data to
|
|
*
|
|
* This function checks for the F2H_MSG_MEM_ALLOC packet version and based on that gets the
|
|
* descriptor data from the packet.
|
|
*/
|
|
static inline void hfi_get_mem_alloc_desc(void *rcvd, struct hfi_mem_alloc_desc *out)
|
|
{
|
|
struct hfi_mem_alloc_cmd_legacy *in_legacy = (struct hfi_mem_alloc_cmd_legacy *)rcvd;
|
|
struct hfi_mem_alloc_cmd *in = (struct hfi_mem_alloc_cmd *)rcvd;
|
|
|
|
if (in->version > 0)
|
|
memcpy(out, &in->desc, sizeof(in->desc));
|
|
else
|
|
memcpy(out, &in_legacy->desc, sizeof(in_legacy->desc));
|
|
}
|
|
|
|
/**
|
|
* hfi_get_gmu_va_alignment - Get the alignment (in bytes) for a GMU VA
|
|
* align: Alignment specified as a power of two (2^n) in bits[0:7]
|
|
*
|
|
* This function derives the GMU VA alignment in bytes from bits[0:7] in the passed in value, which
|
|
* is specified in terms of power of two (2^n). For example, va_align = 20 means (1 << 20) = 1MB
|
|
* alignment. The minimum alignment (in bytes) is SZ_4K i.e. anything less than (or equal to) a
|
|
* va_align value of ilog2(SZ_4K) will default to SZ_4K alignment.
|
|
*/
|
|
static inline u32 hfi_get_gmu_va_alignment(u32 align)
|
|
{
|
|
u32 va_align = FIELD_GET(GENMASK(7, 0), align);
|
|
|
|
return (va_align > ilog2(SZ_4K)) ? (1 << va_align) : SZ_4K;
|
|
}
|
|
|
|
/**
|
|
* hfi_get_gmu_sz_alignment - Get the alignment (in bytes) for GMU mapping size
|
|
* align: Alignment specified as a power of two (2^n) in bits[8:15]
|
|
*
|
|
* This function derives the GMU VA size alignment in bytes from bits[8:15] in the passed in value,
|
|
* which is specified in terms of power of two (2^n). For example, sz_align = 20 means
|
|
* (1 << 20) = 1MB alignment. The minimum alignment (in bytes) is SZ_4K i.e. anything less
|
|
* than (or equal to) a sz_align value of ilog2(SZ_4K) will default to SZ_4K alignment.
|
|
*/
|
|
static inline u32 hfi_get_gmu_sz_alignment(u32 align)
|
|
{
|
|
u32 sz_align = FIELD_GET(GENMASK(15, 8), align);
|
|
|
|
return (sz_align > ilog2(SZ_4K)) ? (1 << sz_align) : SZ_4K;
|
|
}
|
|
|
|
/**
|
|
* adreno_hwsched_wait_ack_completion - Wait for HFI ack asynchronously
|
|
* adreno_dev: Pointer to the adreno device
|
|
* dev: Pointer to the device structure
|
|
* ack: Pointer to the pending ack
|
|
* process_msgq: Function pointer to the msgq processing function
|
|
*
|
|
* This function waits for the completion structure, which gets signaled asynchronously. In case
|
|
* there is a timeout, process the msgq one last time. If the ack is present, log an error and move
|
|
* on. If the ack isn't present, log an error, take a snapshot and return -ETIMEDOUT.
|
|
*
|
|
* Return: 0 on success and -ETIMEDOUT on failure
|
|
*/
|
|
int adreno_hwsched_wait_ack_completion(struct adreno_device *adreno_dev,
|
|
struct device *dev, struct pending_cmd *ack,
|
|
void (*process_msgq)(struct adreno_device *adreno_dev));
|
|
|
|
/**
|
|
* adreno_hwsched_ctxt_unregister_wait_completion - Wait for HFI ack for context unregister
|
|
* adreno_dev: Pointer to the adreno device
|
|
* dev: Pointer to the device structure
|
|
* ack: Pointer to the pending ack
|
|
* process_msgq: Function pointer to the msgq processing function
|
|
* cmd: Pointer to the hfi packet header and data
|
|
*
|
|
* This function waits for the completion structure for context unregister hfi ack,
|
|
* which gets signaled asynchronously. In case there is a timeout, process the msgq
|
|
* one last time. If the ack is present, log an error and move on. If the ack isn't
|
|
* present, log an error and return -ETIMEDOUT.
|
|
*
|
|
* Return: 0 on success and -ETIMEDOUT on failure
|
|
*/
|
|
int adreno_hwsched_ctxt_unregister_wait_completion(
|
|
struct adreno_device *adreno_dev,
|
|
struct device *dev, struct pending_cmd *ack,
|
|
void (*process_msgq)(struct adreno_device *adreno_dev),
|
|
struct hfi_unregister_ctxt_cmd *cmd);
|
|
|
|
/**
|
|
* hfi_get_minidump_string - Get the va-minidump string from entry
|
|
* mem_kind: mem_kind type
|
|
* hfi_minidump_str: Pointer to the output string
|
|
* size: Max size of the hfi_minidump_str
|
|
* rb_id: Pointer to the rb_id count
|
|
*
|
|
* This function return 0 on valid mem_kind and copies the VA-MINIDUMP string to
|
|
* hfi_minidump_str else return error
|
|
*/
|
|
static inline int hfi_get_minidump_string(u32 mem_kind, char *hfi_minidump_str,
|
|
size_t size, u32 *rb_id)
|
|
{
|
|
/* Extend this if the VA mindump need more hfi alloc entries */
|
|
switch (mem_kind) {
|
|
case HFI_MEMKIND_RB:
|
|
snprintf(hfi_minidump_str, size, KGSL_GMU_RB_ENTRY"_%d", (*rb_id)++);
|
|
break;
|
|
case HFI_MEMKIND_SCRATCH:
|
|
snprintf(hfi_minidump_str, size, KGSL_SCRATCH_ENTRY);
|
|
break;
|
|
case HFI_MEMKIND_PROFILE:
|
|
snprintf(hfi_minidump_str, size, KGSL_GMU_KERNEL_PROF_ENTRY);
|
|
break;
|
|
case HFI_MEMKIND_USER_PROFILE_IBS:
|
|
snprintf(hfi_minidump_str, size, KGSL_GMU_USER_PROF_ENTRY);
|
|
break;
|
|
case HFI_MEMKIND_CMD_BUFFER:
|
|
snprintf(hfi_minidump_str, size, KGSL_GMU_CMD_BUFFER_ENTRY);
|
|
break;
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|