mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 04:42:04 -04:00
msm: cvp: Add DSP error handling
CVP driver will retry and bail out in case DSP reports error. Change-Id: I595cc31b40ce61aaa000a68f62400aacc1508e76 Signed-off-by: George Shen <sqiao@codeaurora.org>
This commit is contained in:
parent
1565876acc
commit
a0ca0f0929
2 changed files with 231 additions and 10 deletions
|
|
@ -17,6 +17,8 @@ static int dspVMperm[DSP_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC,
|
|||
PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||
static int hlosVMperm[HLOS_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||
|
||||
static int cvp_reinit_dsp(void);
|
||||
|
||||
static int cvp_dsp_send_cmd(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
|
|
@ -40,7 +42,8 @@ exit:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
||||
static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd,
|
||||
uint32_t len, struct cvp_dsp_rsp_msg *rsp)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
|
@ -63,12 +66,15 @@ static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
|||
}
|
||||
|
||||
exit:
|
||||
rsp->ret = me->pending_dsp2cpu_rsp.ret;
|
||||
rsp->dsp_state = me->pending_dsp2cpu_rsp.dsp_state;
|
||||
me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
||||
uint32_t size_in_bytes)
|
||||
uint32_t size_in_bytes,
|
||||
struct cvp_dsp_rsp_msg *rsp)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cvp_dsp_cmd_msg cmd;
|
||||
|
|
@ -88,7 +94,7 @@ static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
|||
"%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n",
|
||||
__func__, phys_addr, size_in_bytes, cmd.ddr_type);
|
||||
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||
|
|
@ -224,6 +230,8 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||
int rc = 0;
|
||||
struct cvp_dsp_cmd_msg cmd;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
bool retried = false;
|
||||
|
||||
cmd.type = CPU2DSP_SUSPEND;
|
||||
|
||||
|
|
@ -231,8 +239,11 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||
if (me->state != DSP_READY)
|
||||
goto exit;
|
||||
|
||||
retry:
|
||||
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd,
|
||||
sizeof(struct cvp_dsp_cmd_msg),
|
||||
&rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||
|
|
@ -240,8 +251,31 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
me->state = DSP_SUSPEND;
|
||||
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||
goto fatal_exit;
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||
if (!retried) {
|
||||
mutex_unlock(&me->lock);
|
||||
retried = true;
|
||||
rc = cvp_reinit_dsp();
|
||||
mutex_lock(&me->lock);
|
||||
if (rc)
|
||||
goto fatal_exit;
|
||||
else
|
||||
goto retry;
|
||||
} else {
|
||||
goto fatal_exit;
|
||||
}
|
||||
}
|
||||
|
||||
me->state = DSP_SUSPEND;
|
||||
goto exit;
|
||||
|
||||
fatal_exit:
|
||||
me->state = DSP_INVALID;
|
||||
cvp_hyp_assign_from_dsp();
|
||||
rc = -ENOTSUPP;
|
||||
exit:
|
||||
mutex_unlock(&me->lock);
|
||||
return rc;
|
||||
|
|
@ -252,6 +286,7 @@ int cvp_dsp_resume(uint32_t session_flag)
|
|||
int rc = 0;
|
||||
struct cvp_dsp_cmd_msg cmd;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
|
||||
cmd.type = CPU2DSP_RESUME;
|
||||
|
||||
|
|
@ -260,7 +295,9 @@ int cvp_dsp_resume(uint32_t session_flag)
|
|||
goto exit;
|
||||
|
||||
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd,
|
||||
sizeof(struct cvp_dsp_cmd_msg),
|
||||
&rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||
|
|
@ -280,6 +317,7 @@ int cvp_dsp_shutdown(uint32_t session_flag)
|
|||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
int rc = 0;
|
||||
struct cvp_dsp_cmd_msg cmd;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
|
||||
cmd.type = CPU2DSP_SHUTDOWN;
|
||||
|
||||
|
|
@ -288,7 +326,7 @@ int cvp_dsp_shutdown(uint32_t session_flag)
|
|||
goto exit;
|
||||
|
||||
me->state = DSP_INACTIVE;
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with rc = %d\n",
|
||||
|
|
@ -312,6 +350,8 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||
struct cvp_dsp_cmd_msg cmd;
|
||||
int rc;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
bool retried = false;
|
||||
|
||||
cmd.type = CPU2DSP_REGISTER_BUFFER;
|
||||
cmd.session_id = session_id;
|
||||
|
|
@ -330,12 +370,43 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||
__func__, cmd.buff_size, cmd.session_id);
|
||||
|
||||
mutex_lock(&me->lock);
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
retry:
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFAIL || rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||
dprintk(CVP_WARN, "%s, DSP return err %d\n", __func__, rsp.ret);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||
goto fatal_exit;
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||
if (!retried) {
|
||||
mutex_unlock(&me->lock);
|
||||
retried = true;
|
||||
rc = cvp_reinit_dsp();
|
||||
mutex_lock(&me->lock);
|
||||
if (rc)
|
||||
goto fatal_exit;
|
||||
else
|
||||
goto retry;
|
||||
} else {
|
||||
goto fatal_exit;
|
||||
}
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
fatal_exit:
|
||||
me->state = DSP_INVALID;
|
||||
cvp_hyp_assign_from_dsp();
|
||||
rc = -ENOTSUPP;
|
||||
exit:
|
||||
mutex_unlock(&me->lock);
|
||||
return rc;
|
||||
|
|
@ -349,6 +420,8 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||
struct cvp_dsp_cmd_msg cmd;
|
||||
int rc;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
bool retried = false;
|
||||
|
||||
cmd.type = CPU2DSP_DEREGISTER_BUFFER;
|
||||
cmd.session_id = session_id;
|
||||
|
|
@ -367,12 +440,43 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||
__func__, cmd.buff_size, cmd.session_id);
|
||||
|
||||
mutex_lock(&me->lock);
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
||||
retry:
|
||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFAIL || rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||
dprintk(CVP_WARN, "%s, DSP return err %d\n", __func__, rsp.ret);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||
goto fatal_exit;
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||
if (!retried) {
|
||||
mutex_unlock(&me->lock);
|
||||
retried = true;
|
||||
rc = cvp_reinit_dsp();
|
||||
mutex_lock(&me->lock);
|
||||
if (rc)
|
||||
goto fatal_exit;
|
||||
else
|
||||
goto retry;
|
||||
} else {
|
||||
goto fatal_exit;
|
||||
}
|
||||
}
|
||||
|
||||
goto exit;
|
||||
|
||||
fatal_exit:
|
||||
me->state = DSP_INVALID;
|
||||
cvp_hyp_assign_from_dsp();
|
||||
rc = -ENOTSUPP;
|
||||
exit:
|
||||
mutex_unlock(&me->lock);
|
||||
return rc;
|
||||
|
|
@ -455,11 +559,94 @@ void cvp_dsp_init_hfi_queue_hdr(struct iris_hfi_device *device)
|
|||
q_hdr->qhdr_rx_req = 0;
|
||||
}
|
||||
|
||||
static int __reinit_dsp(void)
|
||||
{
|
||||
int rc;
|
||||
uint32_t flag = 0;
|
||||
uint64_t addr;
|
||||
uint32_t size;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
struct msm_cvp_core *core;
|
||||
struct iris_hfi_device *device;
|
||||
|
||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||
if (core && core->device)
|
||||
device = core->device->hfi_device_data;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (!device) {
|
||||
dprintk(CVP_ERR, "%s: NULL device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Force shutdown DSP */
|
||||
rc = cvp_dsp_shutdown(flag);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Resend HFI queue */
|
||||
mutex_lock(&me->lock);
|
||||
if (!device->dsp_iface_q_table.align_virtual_addr) {
|
||||
dprintk(CVP_ERR, "%s: DSP HFI queue released\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle;
|
||||
size = device->dsp_iface_q_table.mem_data.size;
|
||||
|
||||
if (!addr || !size) {
|
||||
dprintk(CVP_DSP, "%s: HFI queue is not ready\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = cvp_hyp_assign_to_dsp(addr, size);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "%s: cvp_hyp_assign_to_dsp. rc=%d\n",
|
||||
__func__, rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size, &rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
|
||||
__func__, rc);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
if (rsp.ret) {
|
||||
dprintk(CVP_ERR, "%s: DSP error %d %d\n", __func__,
|
||||
rsp.ret, rsp.dsp_state);
|
||||
rc = -ENODEV;
|
||||
}
|
||||
exit:
|
||||
mutex_unlock(&me->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cvp_reinit_dsp(void)
|
||||
{
|
||||
int rc;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
rc = __reinit_dsp();
|
||||
if (rc) {
|
||||
mutex_lock(&me->lock);
|
||||
me->state = DSP_INVALID;
|
||||
cvp_hyp_assign_from_dsp();
|
||||
mutex_unlock(&me->lock);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void cvp_dsp_send_hfi_queue(void)
|
||||
{
|
||||
struct msm_cvp_core *core;
|
||||
struct iris_hfi_device *device;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
struct cvp_dsp_rsp_msg rsp;
|
||||
uint64_t addr;
|
||||
uint32_t size;
|
||||
int rc;
|
||||
|
|
@ -511,7 +698,7 @@ void cvp_dsp_send_hfi_queue(void)
|
|||
"%s: Done init of HFI queue headers\n", __func__);
|
||||
}
|
||||
|
||||
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size);
|
||||
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size, &rsp);
|
||||
if (rc) {
|
||||
dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
|
||||
__func__, rc);
|
||||
|
|
@ -519,6 +706,30 @@ void cvp_dsp_send_hfi_queue(void)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||
dprintk(CVP_WARN, "%s unsupported cmd %d\n",
|
||||
__func__, rsp.type);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (rsp.ret == CPU2DSP_EFATAL || rsp.ret == CPU2DSP_EUNAVAILABLE) {
|
||||
dprintk(CVP_ERR, "%s fatal error returned %d\n",
|
||||
__func__, rsp.dsp_state);
|
||||
me->state = DSP_INVALID;
|
||||
cvp_hyp_assign_from_dsp();
|
||||
goto exit;
|
||||
} else if (rsp.ret == CPU2DSP_EINVALSTATE) {
|
||||
dprintk(CVP_ERR, "%s dsp invalid state %d\n",
|
||||
__func__, rsp.dsp_state);
|
||||
mutex_unlock(&me->lock);
|
||||
if (cvp_reinit_dsp()) {
|
||||
dprintk(CVP_ERR, "%s reinit dsp fail\n", __func__);
|
||||
mutex_unlock(&device->lock);
|
||||
return;
|
||||
}
|
||||
mutex_lock(&me->lock);
|
||||
}
|
||||
|
||||
dprintk(CVP_DSP, "%s: dsp initialized\n", __func__);
|
||||
me->state = DSP_READY;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ void cvp_dsp_device_exit(void);
|
|||
void cvp_dsp_send_hfi_queue(void);
|
||||
void cvp_dsp_init_hfi_queue_hdr(struct iris_hfi_device *device);
|
||||
|
||||
enum CPU2DSP_STATUS {
|
||||
CPU2DSP_SUCCESS = 0,
|
||||
CPU2DSP_EFAIL = 1,
|
||||
CPU2DSP_EFATAL = 2,
|
||||
CPU2DSP_EUNAVAILABLE = 3,
|
||||
CPU2DSP_EINVALSTATE = 4,
|
||||
CPU2DSP_EUNSUPPORTED = 5,
|
||||
};
|
||||
|
||||
enum CVP_DSP_COMMAND {
|
||||
CPU2DSP_SEND_HFI_QUEUE = 0,
|
||||
CPU2DSP_SUSPEND = 1,
|
||||
|
|
@ -59,7 +68,8 @@ struct cvp_dsp_cmd_msg {
|
|||
struct cvp_dsp_rsp_msg {
|
||||
uint32_t type;
|
||||
int32_t ret;
|
||||
uint32_t reserved[CVP_DSP_MAX_RESERVED];
|
||||
uint32_t dsp_state;
|
||||
uint32_t reserved[CVP_DSP_MAX_RESERVED - 1];
|
||||
};
|
||||
|
||||
struct cvp_dsp2cpu_cmd_msg {
|
||||
|
|
|
|||
Loading…
Reference in a new issue