msm: eva: mmap firmware debug memory

For user mode to save into a dump file. It helps FW debugging.

Change-Id: I1c9c52d27d0dfd20e3eeb54b203416f6df095c8d
Signed-off-by: George Shen <quic_sqiao@quicinc.com>
This commit is contained in:
George Shen
2023-06-13 14:03:38 -07:00
committed by Gerrit - the friendly Code Review server
parent aafc38db81
commit ea94318515
5 changed files with 138 additions and 39 deletions

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef __MSM_EVA_PRIVATE_H__
#define __MSM_EVA_PRIVATE_H__
@@ -139,6 +140,7 @@ struct eva_kmd_hfi_packet {
#define EVA_KMD_PROP_SESSION_DSPMASK 6
#define EVA_KMD_PROP_SESSION_DUMPOFFSET 7
#define EVA_KMD_PROP_SESSION_DUMPSIZE 8
#define EVA_KMD_PROP_SESSION_ERROR 9
#define EVA_KMD_PROP_PWR_FDU 0x10
#define EVA_KMD_PROP_PWR_ICA 0x11

View File

@@ -2531,8 +2531,8 @@ static int iris_debug_hook(void *device)
dprintk(CVP_ERR, "%s Invalid device\n", __func__);
return -ENODEV;
}
__write_register(dev, CVP_WRAPPER_CORE_CLOCK_CONFIG, 0x11);
__write_register(dev, CVP_WRAPPER_TZ_CPU_CLOCK_CONFIG, 0x1);
//__write_register(dev, CVP_WRAPPER_CORE_CLOCK_CONFIG, 0x11);
//__write_register(dev, CVP_WRAPPER_TZ_CPU_CLOCK_CONFIG, 0x1);
dprintk(CVP_ERR, "Halt Tensilica and core and axi\n");
return 0;

View File

@@ -207,7 +207,7 @@ static int msm_cvp_session_process_hfi(
}
if (is_config_pkt)
pr_info(CVP_DBG_TAG "inst %pK config %s\n", "sess",
pr_info_ratelimited(CVP_DBG_TAG "inst %pK config %s\n", "sess",
inst, cvp_hfi_defs[pkt_idx].name);
if (signal == HAL_NO_RESP) {
@@ -657,7 +657,7 @@ static int cvp_enqueue_pkt(struct msm_cvp_inst* inst,
if (map_type == MAP_PERSIST)
rc = msm_cvp_map_user_persist(inst, in_pkt, in_offset, in_buf_num);
else if (map_type == UNMAP_PERSIST)
rc = msm_cvp_mark_user_persist(inst, in_pkt, in_offset, in_buf_num);
rc = msm_cvp_unmap_user_persist(inst, in_pkt, in_offset, in_buf_num);
else
rc = msm_cvp_map_frame(inst, in_pkt, in_offset, in_buf_num);
@@ -893,7 +893,8 @@ int msm_cvp_session_start(struct msm_cvp_inst *inst,
goto stop_thread;
}
dprintk(CVP_SESS, "session %llx (%#x) started\n", inst, hash32_ptr(inst->session));
pr_info_ratelimited(CVP_DBG_TAG "session %llx (%#x) started\n",
"sess", inst, hash32_ptr(inst->session));
return 0;
@@ -942,8 +943,8 @@ int msm_cvp_session_stop(struct msm_cvp_inst *inst,
}
sq->state = QUEUE_STOP;
dprintk(CVP_SESS, "Stop session: %pK session_id = %d\n",
inst, hash32_ptr(inst->session));
pr_info_ratelimited(CVP_DBG_TAG "Stop session: %pK session_id = %d\n",
"sess", inst, hash32_ptr(inst->session));
spin_unlock(&sq->lock);
hdev = inst->core->device;
@@ -1076,6 +1077,18 @@ static int msm_cvp_get_sysprop(struct msm_cvp_inst *inst,
session_prop->dump_size;
break;
}
case EVA_KMD_PROP_SESSION_ERROR:
{
rc = dma_buf_fd(hfi->mem_addr.mem_data.dma_buf, O_RDONLY | O_CLOEXEC);
if (rc < 0) {
dprintk(CVP_WARN, "Failed get dma_buf fd %d\n", rc);
break;
}
props->prop_data[i].data = rc;
rc = 0;
break;
}
case EVA_KMD_PROP_PWR_FDU:
{
props->prop_data[i].data =

View File

@@ -1418,16 +1418,67 @@ exit:
return smem;
}
static u32 msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
static int msm_cvp_unmap_user_persist_buf(struct msm_cvp_inst *inst,
struct cvp_buf_type *buf,
u32 pkt_type, u32 buf_idx)
u32 pkt_type, u32 buf_idx, u32 *iova)
{
struct msm_cvp_smem *smem = NULL;
struct list_head *ptr;
struct list_head *next;
struct cvp_internal_buf *pbuf;
struct dma_buf *dma_buf;
if (!inst) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
return -EINVAL;
}
dma_buf = msm_cvp_smem_get_dma_buf(buf->fd);
if (!dma_buf)
return -EINVAL;
mutex_lock(&inst->persistbufs.lock);
list_for_each_safe(ptr, next, &inst->persistbufs.list) {
if (!ptr) {
mutex_unlock(&inst->persistbufs.lock);
return -EINVAL;
}
pbuf = list_entry(ptr, struct cvp_internal_buf, list);
if (dma_buf == pbuf->smem->dma_buf && (pbuf->smem->flags & SMEM_PERSIST)) {
*iova = pbuf->smem->device_addr;
dprintk(CVP_MEM,
"Unmap persist fd %d, dma_buf %#llx iova %#x\n",
pbuf->fd, pbuf->smem->dma_buf, *iova);
list_del(&pbuf->list);
if (*iova) {
msm_cvp_unmap_smem(inst, pbuf->smem, "unmap user persist");
msm_cvp_smem_put_dma_buf(pbuf->smem->dma_buf);
pbuf->smem->device_addr = 0;
}
cvp_kmem_cache_free(&cvp_driver->smem_cache, smem);
pbuf->smem = NULL;
cvp_kmem_cache_free(&cvp_driver->buf_cache, pbuf);
mutex_unlock(&inst->persistbufs.lock);
dma_buf_put(dma_buf);
return 0;
}
}
mutex_unlock(&inst->persistbufs.lock);
dma_buf_put(dma_buf);
return -EINVAL;
}
static int msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
struct cvp_buf_type *buf,
u32 pkt_type, u32 buf_idx, u32 *iova)
{
u32 iova = 0;
struct msm_cvp_smem *smem = NULL;
struct list_head *ptr;
struct list_head *next;
struct cvp_internal_buf *pbuf;
struct dma_buf *dma_buf;
int ret;
if (!inst) {
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
@@ -1441,24 +1492,24 @@ static u32 msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
mutex_lock(&inst->persistbufs.lock);
if (!inst->persistbufs.list.next) {
mutex_unlock(&inst->persistbufs.lock);
return 0;
return -EINVAL;
}
list_for_each_safe(ptr, next, &inst->persistbufs.list) {
if (!ptr)
return 0;
return -EINVAL;
pbuf = list_entry(ptr, struct cvp_internal_buf, list);
if (dma_buf == pbuf->smem->dma_buf) {
pbuf->size =
(pbuf->size >= buf->size) ?
pbuf->size : buf->size;
iova = pbuf->smem->device_addr + buf->offset;
*iova = pbuf->smem->device_addr + buf->offset;
mutex_unlock(&inst->persistbufs.lock);
atomic_inc(&pbuf->smem->refcount);
dma_buf_put(dma_buf);
dprintk(CVP_MEM,
"map persist Reuse fd %d, dma_buf %#llx\n",
pbuf->fd, pbuf->smem->dma_buf);
return iova;
return 0;
}
}
mutex_unlock(&inst->persistbufs.lock);
@@ -1469,7 +1520,7 @@ static u32 msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
if (!pbuf) {
dprintk(CVP_ERR, "%s failed to allocate kmem obj\n",
__func__);
return 0;
return -ENOMEM;
}
if (is_params_pkt(pkt_type))
@@ -1477,8 +1528,10 @@ static u32 msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
else
smem = msm_cvp_session_get_smem(inst, buf, true, pkt_type);
if (!smem)
if (!smem) {
ret = -ENOMEM;
goto exit;
}
smem->pkt_type = pkt_type;
smem->buf_idx = buf_idx;
@@ -1495,13 +1548,13 @@ static u32 msm_cvp_map_user_persist_buf(struct msm_cvp_inst *inst,
print_internal_buffer(CVP_MEM, "map persist", inst, pbuf);
iova = smem->device_addr + buf->offset;
*iova = smem->device_addr + buf->offset;
return iova;
return 0;
exit:
cvp_kmem_cache_free(&cvp_driver->buf_cache, pbuf);
return 0;
return ret;
}
static u32 msm_cvp_map_frame_buf(struct msm_cvp_inst *inst,
@@ -1651,21 +1704,18 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid)
dprintk(CVP_WARN, "%s frame %llu not found!\n", __func__, ktid);
}
int msm_cvp_mark_user_persist(struct msm_cvp_inst *inst,
struct eva_kmd_hfi_packet *in_pkt,
unsigned int offset, unsigned int buf_num)
{
dprintk(CVP_ERR, "Unexpected user persistent buffer release\n");
return 0;
}
int msm_cvp_map_user_persist(struct msm_cvp_inst *inst,
/*
* Unmap persistent buffer before sending RELEASE_PERSIST_BUFFERS to FW
* This packet is sent after SESSION_STOP. The assumption is FW/HW will
* NOT access any of the 3 persist buffer.
*/
int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
struct eva_kmd_hfi_packet *in_pkt,
unsigned int offset, unsigned int buf_num)
{
struct cvp_buf_type *buf;
struct cvp_hfi_cmd_session_hdr *cmd_hdr;
int i;
int i, ret;
u32 iova;
if (!offset || !buf_num)
@@ -1679,14 +1729,48 @@ int msm_cvp_map_user_persist(struct msm_cvp_inst *inst,
if (buf->fd < 0 || !buf->size)
continue;
iova = msm_cvp_map_user_persist_buf(inst, buf,
cmd_hdr->packet_type, i);
if (!iova) {
ret = msm_cvp_unmap_user_persist_buf(inst, buf,
cmd_hdr->packet_type, i, &iova);
if (ret) {
dprintk(CVP_ERR,
"%s: buf %d register failed.\n",
"%s: buf %d unmap failed.\n",
__func__, i);
return -EINVAL;
return ret;
}
buf->fd = iova;
}
return 0;
}
int msm_cvp_map_user_persist(struct msm_cvp_inst *inst,
struct eva_kmd_hfi_packet *in_pkt,
unsigned int offset, unsigned int buf_num)
{
struct cvp_buf_type *buf;
struct cvp_hfi_cmd_session_hdr *cmd_hdr;
int i, ret;
u32 iova;
if (!offset || !buf_num)
return 0;
cmd_hdr = (struct cvp_hfi_cmd_session_hdr *)in_pkt;
for (i = 0; i < buf_num; i++) {
buf = (struct cvp_buf_type *)&in_pkt->pkt_data[offset];
offset += sizeof(*buf) >> 2;
if (buf->fd < 0 || !buf->size)
continue;
ret = msm_cvp_map_user_persist_buf(inst, buf,
cmd_hdr->packet_type, i, &iova);
if (ret) {
dprintk(CVP_ERR,
"%s: buf %d map failed.\n",
__func__, i);
return ret;
}
buf->fd = iova;
}

View File

@@ -113,11 +113,11 @@ static inline void DEINIT_DMAMAP_CACHE(struct cvp_dmamap_cache *cache)
#define INPUT_FENCE_BITMASK 0x1
#define OUTPUT_FENCE_BITMASK 0x2
/* Track source of dma_buf allocator/owner */
enum buffer_owner {
DRIVER,
FIRMWARE,
CLIENT,
DSP,
DRIVER, /* Allocated by KMD, for CPU driver */
CLIENT, /* Allocated by Client (DSP or CPU) */
DSP, /* Allocated by KMD, for DSP driver */
MAX_OWNER
};
@@ -219,7 +219,7 @@ int msm_cvp_proc_oob(struct msm_cvp_inst* inst,
struct eva_kmd_hfi_packet* in_pkt);
void msm_cvp_cache_operations(struct msm_cvp_smem *smem,
u32 type, u32 offset, u32 size);
int msm_cvp_mark_user_persist(struct msm_cvp_inst *inst,
int msm_cvp_unmap_user_persist(struct msm_cvp_inst *inst,
struct eva_kmd_hfi_packet *in_pkt,
unsigned int offset, unsigned int buf_num);
int msm_cvp_map_user_persist(struct msm_cvp_inst *inst,