mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "soc: qcom: hgsl: Support cooperative reset with DBQ"
This commit is contained in:
commit
5f2c4c9c6f
2 changed files with 274 additions and 105 deletions
|
|
@ -26,11 +26,11 @@
|
|||
#include <linux/regmap.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <uapi/linux/hgsl.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include "hgsl.h"
|
||||
#include "hgsl_tcsr.h"
|
||||
|
||||
#define HGSL_DEVICE_NAME "hgsl"
|
||||
#define HGSL_DEVICE_NAME "hgsl"
|
||||
#define HGSL_DEV_NUM 1
|
||||
|
||||
/* Support upto 3 GVMs: 3 DBQs(Low/Medium/High priority) per GVM */
|
||||
|
|
@ -40,15 +40,15 @@
|
|||
#define IORESOURCE_GMUCX "hgsl_reg_gmucx"
|
||||
|
||||
/* Set-up profiling packets as needed by scope */
|
||||
#define CMDBATCH_PROFILING 0x00000010
|
||||
#define CMDBATCH_PROFILING 0x00000010
|
||||
|
||||
/* Ping the user of HFI when this command is done */
|
||||
#define CMDBATCH_NOTIFY 0x00000020
|
||||
#define CMDBATCH_NOTIFY 0x00000020
|
||||
|
||||
#define CMDBATCH_EOF 0x00000100
|
||||
#define CMDBATCH_EOF 0x00000100
|
||||
|
||||
/* timeout of waiting for free space of doorbell queue. */
|
||||
#define HGSL_IDLE_TIMEOUT msecs_to_jiffies(1000)
|
||||
/* Max retry count of waiting for free space of doorbell queue. */
|
||||
#define HGSL_QFREE_MAX_RETRY_COUNT (500)
|
||||
#define GLB_DB_SRC_ISSUEIB_IRQ_ID_0 TCSR_SRC_IRQ_ID_0
|
||||
#define GLB_DB_SRC_ISSUEIB_IRQ_ID_1 TCSR_SRC_IRQ_ID_1
|
||||
#define GLB_DB_SRC_ISSUEIB_IRQ_ID_2 TCSR_SRC_IRQ_ID_2
|
||||
|
|
@ -76,78 +76,122 @@ struct db_buffer {
|
|||
#define QHDR_STATUS_INACTIVE 0x00
|
||||
#define QHDR_STATUS_ACTIVE 0x01
|
||||
|
||||
/* Updated by HGSL */
|
||||
#define DBQ_WRITE_INDEX_IN_DWORD 0
|
||||
#define HGSL_CONTEXT_NUM (128)
|
||||
#define HGSL_SEND_MSG_MAX_RETRY_COUNT (150)
|
||||
|
||||
/* Updated by GMU */
|
||||
#define DBQ_READ_INDEX_IN_DWORD 1
|
||||
// Skip all commands from the bad context
|
||||
#define HGSL_FT_POLICY_FLAG_KILL BIT(2)
|
||||
|
||||
#define HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD (1536 >> 2)
|
||||
#define HGSL_DBQ_CONTEXT_INFO_BASE_OFFSET_IN_DWORD (2048 >> 2)
|
||||
#define ALIGN_ADDRESS_4DWORD(addr) (((addr)+15) & ((long long) ~15))
|
||||
#define ALIGN_DWORD_ADDRESS_4DWORD(dwaddr) (ALIGN_ADDRESS_4DWORD((dwaddr) * \
|
||||
sizeof(uint32_t)) / sizeof(uint32_t))
|
||||
|
||||
#define HGSL_CONTEXT_NUM 128
|
||||
enum HGSL_DBQ_METADATA_COMMAND_INFO {
|
||||
HGSL_DBQ_METADATA_CONTEXT_INFO,
|
||||
HGSL_DBQ_METADATA_QUEUE_INDEX,
|
||||
HGSL_DBQ_METADATA_COOPERATIVE_RESET,
|
||||
};
|
||||
|
||||
/* Meta info for context */
|
||||
enum HGSL_DBQ_METADATA_INFO {
|
||||
HGSL_DBQ_METADATA_CTXT_ID_IN_DWORD = 0x0,
|
||||
HGSL_DBQ_METADATA_TIMESTAMP_IN_DWORD = 0x1,
|
||||
HGSL_DBQ_METADATA_CTXT_DESTROY_IN_DWORD = 0x2,
|
||||
HGSL_DBQ_METADATA_TOTAL_ENTITY_NUM,
|
||||
/* The context metadata size is 2K in DBQ,
|
||||
* so we can have maximum 4 dwords for each context
|
||||
*/
|
||||
HGSL_DBQ_METADATA_TOTAL_ENTITY_MAX = 0x4
|
||||
#define HGSL_DBQ_CONTEXT_ANY (0x0)
|
||||
#define HGSL_DBQ_OFFSET_ZERO (0x0)
|
||||
|
||||
#define HGSL_DBQ_WRITE_INDEX_OFFSET_IN_DWORD (0x0)
|
||||
#define HGSL_DBQ_READ_INDEX_OFFSET_IN_DWORD (0x1)
|
||||
|
||||
enum HGSL_DBQ_METADATA_COOPERATIVE_RESET_INFO {
|
||||
HGSL_DBQ_HOST_TO_GVM_HARDRESET_REQ,
|
||||
HGSL_DBQ_GVM_TO_HOST_HARDRESET_DISPATCH_IN_BUSY,
|
||||
};
|
||||
|
||||
enum HGSL_DBQ_METADATA_CONTEXT_OFFSET_INFO {
|
||||
HGSL_DBQ_CONTEXT_CONTEXT_ID_OFFSET_IN_DWORD,
|
||||
HGSL_DBQ_CONTEXT_TIMESTAMP_OFFSET_IN_DWORD,
|
||||
HGSL_DBQ_CONTEXT_DESTROY_OFFSET_IN_DWORD,
|
||||
HGSL_DBQ_METADATA_CTXT_TOTAL_ENTITY_NUM,
|
||||
};
|
||||
|
||||
/* DBQ structure
|
||||
* | IBs storage | reserved | w.idx/r.idx | ctxt.info|
|
||||
* ---------------------------------------------------------------------------
|
||||
* | [0] | [1K] | [1.5K] | [2K] |
|
||||
* ---------------------------------------------------------------------------
|
||||
* IBs storage | reserved | w.idx/r.idx | ctxt.info | hard reset |
|
||||
* 0 1K 1.5K 2K 3.5K |
|
||||
* | | | | | |
|
||||
*/
|
||||
static inline void dbq_set_qindex(uint32_t *va_base,
|
||||
uint32_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
uint32_t *dest;
|
||||
|
||||
dest = va_base + HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD + offset;
|
||||
*dest = value;
|
||||
#define HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD (1536 >> 2)
|
||||
#define HGSL_DBQ_CONTEXT_INFO_BASE_OFFSET_IN_DWORD (2048 >> 2)
|
||||
#define HGSL_DBQ_COOPERATIVE_RESET_INFO_BASE_OFFSET_IN_DWORD (3584 >> 2)
|
||||
|
||||
|
||||
static inline bool _timestamp_retired(struct hgsl_context *ctxt,
|
||||
unsigned int timestamp);
|
||||
|
||||
static inline void set_context_timestamp(struct hgsl_context *ctxt,
|
||||
unsigned int ts);
|
||||
static void _signal_contexts(struct qcom_hgsl *hgsl);
|
||||
|
||||
static int db_get_busy_state(void *dbq_base);
|
||||
static void db_set_busy_state(void *dbq_base, int in_busy);
|
||||
|
||||
static uint32_t hgsl_dbq_get_state_info(uint32_t *va_base, uint32_t command,
|
||||
uint32_t ctxt_id, uint32_t offset)
|
||||
{
|
||||
uint32_t *dest = NULL;
|
||||
|
||||
switch (command) {
|
||||
case HGSL_DBQ_METADATA_QUEUE_INDEX:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD +
|
||||
offset);
|
||||
break;
|
||||
case HGSL_DBQ_METADATA_CONTEXT_INFO:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_CONTEXT_INFO_BASE_OFFSET_IN_DWORD +
|
||||
(HGSL_DBQ_METADATA_CTXT_TOTAL_ENTITY_NUM *
|
||||
ctxt_id) + offset);
|
||||
break;
|
||||
case HGSL_DBQ_METADATA_COOPERATIVE_RESET:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_COOPERATIVE_RESET_INFO_BASE_OFFSET_IN_DWORD +
|
||||
offset);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return *dest;
|
||||
}
|
||||
|
||||
static inline uint32_t dbq_get_qindex(uint32_t *va_base,
|
||||
uint32_t offset)
|
||||
static void hgsl_dbq_set_state_info(uint32_t *va_base, uint32_t command,
|
||||
uint32_t ctxt_id, uint32_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
uint32_t *dest;
|
||||
uint32_t val;
|
||||
uint32_t *dest = NULL;
|
||||
|
||||
dest = va_base + HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD + offset;
|
||||
|
||||
val = *dest;
|
||||
|
||||
/* ensure read is done before return */
|
||||
rmb();
|
||||
return val;
|
||||
switch (command) {
|
||||
case HGSL_DBQ_METADATA_QUEUE_INDEX:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_HFI_Q_INDEX_BASE_OFFSET_IN_DWORD +
|
||||
(HGSL_DBQ_METADATA_CTXT_TOTAL_ENTITY_NUM *
|
||||
ctxt_id) + offset);
|
||||
*dest = value;
|
||||
break;
|
||||
case HGSL_DBQ_METADATA_CONTEXT_INFO:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_CONTEXT_INFO_BASE_OFFSET_IN_DWORD +
|
||||
(HGSL_DBQ_METADATA_CTXT_TOTAL_ENTITY_NUM *
|
||||
ctxt_id) + offset);
|
||||
*dest = value;
|
||||
break;
|
||||
case HGSL_DBQ_METADATA_COOPERATIVE_RESET:
|
||||
dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_COOPERATIVE_RESET_INFO_BASE_OFFSET_IN_DWORD +
|
||||
offset);
|
||||
*dest = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void dbq_update_ctxt_info(uint32_t *va_base,
|
||||
uint32_t ctxt_id,
|
||||
uint32_t offset,
|
||||
uint32_t value)
|
||||
{
|
||||
uint32_t *dest = (uint32_t *)(va_base +
|
||||
HGSL_DBQ_CONTEXT_INFO_BASE_OFFSET_IN_DWORD +
|
||||
(HGSL_DBQ_METADATA_TOTAL_ENTITY_NUM * ctxt_id) +
|
||||
offset);
|
||||
|
||||
if (WARN_ON(ctxt_id >= HGSL_CONTEXT_NUM))
|
||||
return;
|
||||
|
||||
*dest = value;
|
||||
}
|
||||
|
||||
#define RGS_HFI_DEFAULT_TIMEOUT_MS 5000
|
||||
|
||||
#define HFI_MSG_TYPE_CMD 0
|
||||
#define HFI_MSG_TYPE_RET 1
|
||||
|
||||
|
|
@ -215,6 +259,18 @@ struct hgsl_fw_ib_desc {
|
|||
uint32_t sz;
|
||||
} __packed;
|
||||
|
||||
struct hfi_msg_header_fields {
|
||||
uint32_t msg_id : 8; ///< 0~127 power, 128~255 eCP
|
||||
uint32_t msg_size_dword : 8; ///< unit in dword, maximum 255
|
||||
uint32_t msg_type : 4; ///< refer to adreno_hfi_msg_type_t
|
||||
uint32_t msg_packet_seq_no : 12;
|
||||
};
|
||||
|
||||
union hfi_msg_header {
|
||||
uint32_t u32_all;
|
||||
struct hfi_msg_header_fields fields;
|
||||
};
|
||||
|
||||
/*
|
||||
* Context ID
|
||||
* cmd_flags
|
||||
|
|
@ -224,7 +280,7 @@ struct hgsl_fw_ib_desc {
|
|||
* An array of IB descriptors
|
||||
*/
|
||||
struct hgsl_db_cmds {
|
||||
uint32_t header;
|
||||
union hfi_msg_header header;
|
||||
uint32_t ctx_id;
|
||||
uint32_t cmd_flags;
|
||||
uint32_t timestamp;
|
||||
|
|
@ -387,18 +443,23 @@ static uint32_t db_queue_freedwords(struct doorbell_queue *dbq)
|
|||
if (dbq == NULL)
|
||||
return 0;
|
||||
|
||||
wptr = dbq_get_qindex(dbq->vbase, DBQ_WRITE_INDEX_IN_DWORD);
|
||||
rptr = dbq_get_qindex(dbq->vbase, DBQ_READ_INDEX_IN_DWORD);
|
||||
wptr = hgsl_dbq_get_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_QUEUE_INDEX, HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_WRITE_INDEX_OFFSET_IN_DWORD);
|
||||
|
||||
rptr = hgsl_dbq_get_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_QUEUE_INDEX, HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_READ_INDEX_OFFSET_IN_DWORD);
|
||||
|
||||
queue_size = dbq->data.dwords;
|
||||
queue_used = (wptr + queue_size - rptr) % queue_size;
|
||||
return (queue_size - queue_used - 1);
|
||||
}
|
||||
|
||||
static int db_queue_wait_freewords(struct doorbell_queue *dbq,
|
||||
uint32_t size)
|
||||
static int db_queue_wait_freewords(struct doorbell_queue *dbq, uint32_t size)
|
||||
{
|
||||
unsigned long t = jiffies + HGSL_IDLE_TIMEOUT;
|
||||
unsigned int retry_count = 0;
|
||||
unsigned int hard_reset_req = false;
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
|
@ -407,13 +468,57 @@ static int db_queue_wait_freewords(struct doorbell_queue *dbq,
|
|||
return -EINVAL;
|
||||
|
||||
do {
|
||||
if (db_queue_freedwords(dbq) >= size)
|
||||
return 0;
|
||||
} while (time_before(jiffies, t));
|
||||
hard_reset_req = hgsl_dbq_get_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_COOPERATIVE_RESET,
|
||||
HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_HOST_TO_GVM_HARDRESET_REQ);
|
||||
|
||||
/* ensure read is done before comparison */
|
||||
rmb();
|
||||
|
||||
if (hard_reset_req == true) {
|
||||
if (db_get_busy_state(dbq->vbase) == true)
|
||||
db_set_busy_state(dbq->vbase, false);
|
||||
} else {
|
||||
if (db_queue_freedwords(dbq) >= size) {
|
||||
db_set_busy_state(dbq->vbase, true);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
udelay(1000);
|
||||
} while (retry_count++ < HGSL_QFREE_MAX_RETRY_COUNT);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int db_get_busy_state(void *dbq_base)
|
||||
{
|
||||
unsigned int busy_state = false;
|
||||
|
||||
busy_state = hgsl_dbq_get_state_info((uint32_t *)dbq_base,
|
||||
HGSL_DBQ_METADATA_COOPERATIVE_RESET,
|
||||
HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_GVM_TO_HOST_HARDRESET_DISPATCH_IN_BUSY);
|
||||
|
||||
/* ensure read is done before comparison */
|
||||
rmb();
|
||||
|
||||
return busy_state;
|
||||
}
|
||||
|
||||
static void db_set_busy_state(void *dbq_base, int in_busy)
|
||||
{
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq_base,
|
||||
HGSL_DBQ_METADATA_COOPERATIVE_RESET,
|
||||
HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_GVM_TO_HOST_HARDRESET_DISPATCH_IN_BUSY,
|
||||
in_busy);
|
||||
|
||||
/* confirm write to memory done */
|
||||
wmb();
|
||||
}
|
||||
|
||||
static int db_send_msg(struct hgsl_priv *priv,
|
||||
struct db_msg_id *db_msg_id,
|
||||
struct db_msg_request *msg_req,
|
||||
|
|
@ -427,11 +532,36 @@ static int db_send_msg(struct hgsl_priv *priv,
|
|||
struct qcom_hgsl *hgsl;
|
||||
struct doorbell_queue *dbq;
|
||||
uint32_t wptr;
|
||||
struct hgsl_db_cmds *cmds;
|
||||
int retry_count = 0;
|
||||
uint32_t hard_reset_req = false;
|
||||
|
||||
hgsl = priv->dev;
|
||||
dbq = &hgsl->dbq[priv->dbq_idx];
|
||||
|
||||
mutex_lock(&hgsl->lock);
|
||||
mutex_lock(&dbq->lock);
|
||||
|
||||
cmds = (struct hgsl_db_cmds *)msg_req->ptr_data;
|
||||
do {
|
||||
hard_reset_req = hgsl_dbq_get_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_COOPERATIVE_RESET,
|
||||
HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_HOST_TO_GVM_HARDRESET_REQ);
|
||||
|
||||
/* ensure read is done before comparison */
|
||||
rmb();
|
||||
|
||||
if (hard_reset_req) {
|
||||
udelay(1000);
|
||||
if (retry_count++ > HGSL_SEND_MSG_MAX_RETRY_COUNT) {
|
||||
ret = -ETIMEDOUT;
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
} while (hard_reset_req);
|
||||
|
||||
db_set_busy_state(dbq->vbase, true);
|
||||
|
||||
queue_size_dword = dbq->data.dwords;
|
||||
msg_size_align = ALIGN(msg_req->msg_dwords, 4);
|
||||
|
||||
|
|
@ -442,7 +572,10 @@ static int db_send_msg(struct hgsl_priv *priv,
|
|||
goto quit;
|
||||
}
|
||||
|
||||
wptr = dbq_get_qindex(dbq->vbase, DBQ_WRITE_INDEX_IN_DWORD);
|
||||
wptr = hgsl_dbq_get_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_QUEUE_INDEX, HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_WRITE_INDEX_OFFSET_IN_DWORD);
|
||||
|
||||
move_dwords = msg_req->msg_dwords;
|
||||
if ((msg_req->msg_dwords + wptr) >= queue_size_dword) {
|
||||
move_dwords = queue_size_dword - wptr;
|
||||
|
|
@ -457,13 +590,22 @@ static int db_send_msg(struct hgsl_priv *priv,
|
|||
memcpy(dst, src, (move_dwords << 2));
|
||||
|
||||
wptr = (wptr + msg_size_align) % queue_size_dword;
|
||||
dbq_set_qindex((uint32_t *)dbq->vbase,
|
||||
DBQ_WRITE_INDEX_IN_DWORD,
|
||||
wptr);
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_QUEUE_INDEX,
|
||||
HGSL_DBQ_CONTEXT_ANY,
|
||||
HGSL_DBQ_WRITE_INDEX_OFFSET_IN_DWORD,
|
||||
wptr);
|
||||
|
||||
dbq_update_ctxt_info((uint32_t *)dbq->vbase,
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_CONTEXT_INFO,
|
||||
cmds->ctx_id,
|
||||
HGSL_DBQ_CONTEXT_CONTEXT_ID_OFFSET_IN_DWORD,
|
||||
cmds->ctx_id);
|
||||
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_CONTEXT_INFO,
|
||||
((struct hgsl_db_cmds *)src)->ctx_id,
|
||||
HGSL_DBQ_METADATA_TIMESTAMP_IN_DWORD,
|
||||
HGSL_DBQ_CONTEXT_TIMESTAMP_OFFSET_IN_DWORD,
|
||||
((struct hgsl_db_cmds *)src)->timestamp);
|
||||
|
||||
/* confirm write to memory done before ring door bell. */
|
||||
|
|
@ -477,7 +619,9 @@ static int db_send_msg(struct hgsl_priv *priv,
|
|||
gmu_ring_local_db(hgsl, priv->dbq_idx);
|
||||
|
||||
quit:
|
||||
mutex_unlock(&hgsl->lock);
|
||||
db_set_busy_state(dbq->vbase, false);
|
||||
|
||||
mutex_unlock(&dbq->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -496,12 +640,14 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv,
|
|||
struct db_msg_id db_msg_id;
|
||||
struct doorbell_queue *dbq;
|
||||
struct qcom_hgsl *hgsl = priv->dev;
|
||||
struct hgsl_context *ctxt;
|
||||
uint32_t seq_num;
|
||||
|
||||
db_msg_id.msg_id = HTOF_MSG_ISSUE_CMD;
|
||||
seq_num = atomic_inc_return(&hgsl->seq_num);
|
||||
db_msg_id.seq_no = seq_num;
|
||||
|
||||
ctxt = hgsl->contexts[ctx_id];
|
||||
dbq = &hgsl->dbq[priv->dbq_idx];
|
||||
|
||||
msg_dwords = MSG_ISSUE_INF_SZ() + MSG_ISSUE_IBS_SZ(num_ibs);
|
||||
|
|
@ -516,9 +662,9 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv,
|
|||
if (cmds == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
cmds->header = HFI_ISSUE_IB_HEADER(num_ibs,
|
||||
msg_dwords,
|
||||
db_msg_id.seq_no);
|
||||
cmds->header = (union hfi_msg_header)HFI_ISSUE_IB_HEADER(num_ibs,
|
||||
msg_dwords,
|
||||
db_msg_id.seq_no);
|
||||
cmds->ctx_id = ctx_id;
|
||||
cmds->num_ibs = num_ibs;
|
||||
cmds->cmd_flags = gmu_cmd_flags;
|
||||
|
|
@ -531,7 +677,19 @@ static int hgsl_db_issue_cmd(struct hgsl_priv *priv,
|
|||
req.msg_dwords = msg_dwords;
|
||||
req.ptr_data = cmds;
|
||||
|
||||
ret = db_send_msg(priv, &db_msg_id, &req, &resp);
|
||||
if (!ctxt->is_killed) {
|
||||
ret = db_send_msg(priv, &db_msg_id, &req, &resp);
|
||||
} else {
|
||||
/* Retire ts immediately*/
|
||||
set_context_timestamp(ctxt, timestamp);
|
||||
|
||||
/* Trigger event to waitfor ts thread */
|
||||
_signal_contexts(hgsl);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ctxt->queued_ts = timestamp;
|
||||
|
||||
kfree(cmds);
|
||||
return ret;
|
||||
|
|
@ -703,8 +861,22 @@ static inline uint32_t get_context_timestamp(struct hgsl_context *ctxt)
|
|||
return ts;
|
||||
}
|
||||
|
||||
static inline void set_context_timestamp(struct hgsl_context *ctxt,
|
||||
unsigned int ts)
|
||||
{
|
||||
unsigned int *ts_mem;
|
||||
|
||||
ts_mem = (unsigned int *)(ctxt->shadow_vbase +
|
||||
ctxt->shadow_eop_off);
|
||||
|
||||
*ts_mem = ts;
|
||||
|
||||
/* ensure update is done before return */
|
||||
wmb();
|
||||
}
|
||||
|
||||
static inline bool _timestamp_retired(struct hgsl_context *ctxt,
|
||||
unsigned int timestamp)
|
||||
unsigned int timestamp)
|
||||
{
|
||||
return (get_context_timestamp(ctxt) >= timestamp);
|
||||
}
|
||||
|
|
@ -937,12 +1109,6 @@ static int hgsl_dbq_init(struct file *filep, unsigned long arg)
|
|||
}
|
||||
WARN_ON(param.head_dwords < 2);
|
||||
|
||||
dbq_set_qindex((uint32_t *)dbq->vbase,
|
||||
DBQ_WRITE_INDEX_IN_DWORD, 0);
|
||||
|
||||
dbq_set_qindex((uint32_t *)dbq->vbase,
|
||||
DBQ_READ_INDEX_IN_DWORD, 0);
|
||||
|
||||
dbq->data.vaddr = dbq->vbase + (param.queue_off_dwords << 2);
|
||||
dbq->data.dwords = param.queue_dwords;
|
||||
|
||||
|
|
@ -994,7 +1160,7 @@ static int hgsl_context_create(struct file *filep, unsigned long arg)
|
|||
}
|
||||
|
||||
if (!hgsl->contexts) {
|
||||
dev_err(hgsl->dev, "DBQ not initialized propertily\n");
|
||||
dev_err(hgsl->dev, "DBQ not initialized properly\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
|
@ -1239,15 +1405,16 @@ static int hgsl_dbq_release(struct file *filep, unsigned long arg,
|
|||
rel_info = *(struct hgsl_dbq_release_info *)arg;
|
||||
|
||||
dbq = &hgsl->dbq[priv->dbq_idx];
|
||||
|
||||
dbq_update_ctxt_info(dbq->vbase,
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_CONTEXT_INFO,
|
||||
rel_info.ctxt_id,
|
||||
HGSL_DBQ_METADATA_CTXT_ID_IN_DWORD,
|
||||
HGSL_DBQ_CONTEXT_CONTEXT_ID_OFFSET_IN_DWORD,
|
||||
rel_info.ctxt_id);
|
||||
|
||||
dbq_update_ctxt_info(dbq->vbase,
|
||||
hgsl_dbq_set_state_info((uint32_t *)dbq->vbase,
|
||||
HGSL_DBQ_METADATA_CONTEXT_INFO,
|
||||
rel_info.ctxt_id,
|
||||
HGSL_DBQ_METADATA_CTXT_DESTROY_IN_DWORD,
|
||||
HGSL_DBQ_CONTEXT_DESTROY_OFFSET_IN_DWORD,
|
||||
1);
|
||||
|
||||
rel_info.ref_count = (dbq->state == DB_STATE_Q_INIT_DONE) ? 1 : 0;
|
||||
|
|
@ -1370,7 +1537,7 @@ out:
|
|||
}
|
||||
|
||||
static int hgsl_ioctl_isync_timeline_create(struct file *filep,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
struct hgsl_priv *priv = filep->private_data;
|
||||
uint32_t param = 0;
|
||||
|
|
@ -1384,7 +1551,7 @@ static int hgsl_ioctl_isync_timeline_create(struct file *filep,
|
|||
}
|
||||
|
||||
static int hgsl_ioctl_isync_timeline_destroy(struct file *filep,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
struct hgsl_priv *priv = filep->private_data;
|
||||
uint32_t param = 0;
|
||||
|
|
@ -1397,7 +1564,7 @@ static int hgsl_ioctl_isync_timeline_destroy(struct file *filep,
|
|||
}
|
||||
|
||||
static int hgsl_ioctl_isync_fence_create(struct file *filep,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
struct hgsl_priv *priv = filep->private_data;
|
||||
struct hgsl_isync_create_fence param;
|
||||
|
|
@ -1418,7 +1585,7 @@ static int hgsl_ioctl_isync_fence_create(struct file *filep,
|
|||
}
|
||||
|
||||
static int hgsl_ioctl_isync_fence_signal(struct file *filep,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
struct hgsl_priv *priv = filep->private_data;
|
||||
struct hgsl_isync_signal_fence param;
|
||||
|
|
@ -1433,7 +1600,7 @@ static int hgsl_ioctl_isync_fence_signal(struct file *filep,
|
|||
}
|
||||
|
||||
static int hgsl_ioctl_isync_forward(struct file *filep,
|
||||
unsigned long arg)
|
||||
unsigned long arg)
|
||||
{
|
||||
struct hgsl_priv *priv = filep->private_data;
|
||||
struct hgsl_isync_forward param;
|
||||
|
|
@ -1518,7 +1685,7 @@ static const struct file_operations hgsl_fops = {
|
|||
};
|
||||
|
||||
static int qcom_hgsl_register(struct platform_device *pdev,
|
||||
struct qcom_hgsl *hgsl_dev)
|
||||
struct qcom_hgsl *hgsl_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -1538,9 +1705,9 @@ static int qcom_hgsl_register(struct platform_device *pdev,
|
|||
}
|
||||
|
||||
hgsl_dev->class_dev = device_create(hgsl_dev->driver_class,
|
||||
NULL,
|
||||
hgsl_dev->device_no,
|
||||
hgsl_dev, HGSL_DEVICE_NAME);
|
||||
NULL,
|
||||
hgsl_dev->device_no,
|
||||
hgsl_dev, HGSL_DEVICE_NAME);
|
||||
|
||||
if (IS_ERR(hgsl_dev->class_dev)) {
|
||||
dev_err(&pdev->dev, "class_device_create failed %d\n", ret);
|
||||
|
|
@ -1553,8 +1720,8 @@ static int qcom_hgsl_register(struct platform_device *pdev,
|
|||
hgsl_dev->cdev.owner = THIS_MODULE;
|
||||
|
||||
ret = cdev_add(&hgsl_dev->cdev,
|
||||
MKDEV(MAJOR(hgsl_dev->device_no), 0),
|
||||
1);
|
||||
MKDEV(MAJOR(hgsl_dev->device_no), 0),
|
||||
1);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "cdev_add failed %d\n", ret);
|
||||
goto exit_destroy_device;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ struct hgsl_context {
|
|||
|
||||
uint32_t last_ts;
|
||||
struct hgsl_hsync_timeline *timeline;
|
||||
uint32_t queued_ts;
|
||||
bool is_killed;
|
||||
};
|
||||
|
||||
struct hgsl_priv {
|
||||
|
|
|
|||
Loading…
Reference in a new issue