disp: msm: sde: handle all error cases during sui transitions
During secure-ui, the SMMU, MISR and VBIF states are altered based on the enable/disable of secure-ui which is followed by the scm_call. Failure in any of the steps would lead the system to an unstable state. Address all the failures and revert back all steps to get the system back in original state to avoid any issues. Change-Id: I736c6cf018c5992ec33806c00e58bf56b818b8a7 Signed-off-by: Veera Sundaram Sankaran <veeras@codeaurora.org> Signed-off-by: Samantha Tran <samtran@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
ca2fbfd531
commit
e4a7d473f9
@@ -334,88 +334,118 @@ static int _sde_kms_scm_call(struct sde_kms *sde_kms, int vmid)
|
||||
|
||||
static int _sde_kms_detach_all_cb(struct sde_kms *sde_kms, u32 vmid)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 ret;
|
||||
|
||||
if (atomic_inc_return(&sde_kms->detach_all_cb) > 1)
|
||||
goto end;
|
||||
return 0;
|
||||
|
||||
/* detach_all_contexts */
|
||||
ret = sde_kms_mmu_detach(sde_kms, false);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to detach all cb ret:%d\n", ret);
|
||||
goto end;
|
||||
goto mmu_error;
|
||||
}
|
||||
|
||||
ret = _sde_kms_scm_call(sde_kms, vmid);
|
||||
if (ret)
|
||||
goto end;
|
||||
if (ret) {
|
||||
SDE_ERROR("scm call failed for vmid:%d\n", vmid);
|
||||
goto scm_error;
|
||||
}
|
||||
|
||||
end:
|
||||
return 0;
|
||||
|
||||
scm_error:
|
||||
sde_kms_mmu_attach(sde_kms, false);
|
||||
mmu_error:
|
||||
atomic_dec(&sde_kms->detach_all_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms, int vmid)
|
||||
static int _sde_kms_attach_all_cb(struct sde_kms *sde_kms, u32 vmid,
|
||||
u32 old_vmid)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 ret;
|
||||
|
||||
if (atomic_dec_return(&sde_kms->detach_all_cb) != 0)
|
||||
goto end;
|
||||
return 0;
|
||||
|
||||
ret = _sde_kms_scm_call(sde_kms, vmid);
|
||||
if (ret)
|
||||
goto end;
|
||||
if (ret) {
|
||||
SDE_ERROR("scm call failed for vmid:%d\n", vmid);
|
||||
goto scm_error;
|
||||
}
|
||||
|
||||
/* attach_all_contexts */
|
||||
ret = sde_kms_mmu_attach(sde_kms, false);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to attach all cb ret:%d\n", ret);
|
||||
goto end;
|
||||
goto mmu_error;
|
||||
}
|
||||
|
||||
end:
|
||||
return 0;
|
||||
|
||||
mmu_error:
|
||||
_sde_kms_scm_call(sde_kms, old_vmid);
|
||||
scm_error:
|
||||
atomic_inc(&sde_kms->detach_all_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_kms_detach_sec_cb(struct sde_kms *sde_kms, int vmid)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 ret;
|
||||
|
||||
if (atomic_inc_return(&sde_kms->detach_sec_cb) > 1)
|
||||
goto end;
|
||||
return 0;
|
||||
|
||||
/* detach secure_context */
|
||||
ret = sde_kms_mmu_detach(sde_kms, true);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to detach sec cb ret:%d\n", ret);
|
||||
goto end;
|
||||
goto mmu_error;
|
||||
}
|
||||
|
||||
ret = _sde_kms_scm_call(sde_kms, vmid);
|
||||
if (ret)
|
||||
goto end;
|
||||
if (ret) {
|
||||
SDE_ERROR("scm call failed for vmid:%d\n", vmid);
|
||||
goto scm_error;
|
||||
}
|
||||
|
||||
end:
|
||||
return 0;
|
||||
|
||||
scm_error:
|
||||
sde_kms_mmu_attach(sde_kms, true);
|
||||
mmu_error:
|
||||
atomic_dec(&sde_kms->detach_sec_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms, int vmid)
|
||||
static int _sde_kms_attach_sec_cb(struct sde_kms *sde_kms, u32 vmid,
|
||||
u32 old_vmid)
|
||||
{
|
||||
u32 ret = 0;
|
||||
u32 ret;
|
||||
|
||||
if (atomic_dec_return(&sde_kms->detach_sec_cb) != 0)
|
||||
goto end;
|
||||
return 0;
|
||||
|
||||
ret = _sde_kms_scm_call(sde_kms, vmid);
|
||||
if (ret)
|
||||
goto end;
|
||||
if (ret) {
|
||||
goto scm_error;
|
||||
SDE_ERROR("scm call failed for vmid:%d\n", vmid);
|
||||
}
|
||||
|
||||
ret = sde_kms_mmu_attach(sde_kms, true);
|
||||
if (ret) {
|
||||
SDE_ERROR("failed to attach sec cb ret:%d\n", ret);
|
||||
goto end;
|
||||
goto mmu_error;
|
||||
}
|
||||
|
||||
end:
|
||||
return 0;
|
||||
|
||||
mmu_error:
|
||||
_sde_kms_scm_call(sde_kms, old_vmid);
|
||||
scm_error:
|
||||
atomic_inc(&sde_kms->detach_sec_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -435,6 +465,7 @@ static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
|
||||
|
||||
ret = _sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, true);
|
||||
if (ret) {
|
||||
sde_crtc_misr_setup(crtc, false, 0);
|
||||
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||
return ret;
|
||||
}
|
||||
@@ -473,8 +504,10 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
|
||||
/* enable sui misr if requested, before the transition */
|
||||
if (smmu_state->sui_misr_state == SUI_MISR_ENABLE_REQ) {
|
||||
ret = _sde_kms_sui_misr_ctrl(sde_kms, crtc, true);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
smmu_state->sui_misr_state == NONE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&sde_kms->secure_transition_lock);
|
||||
@@ -486,7 +519,8 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
|
||||
break;
|
||||
|
||||
case ATTACH_ALL_REQ:
|
||||
ret = _sde_kms_attach_all_cb(sde_kms, VMID_CP_PIXEL);
|
||||
ret = _sde_kms_attach_all_cb(sde_kms, VMID_CP_PIXEL,
|
||||
VMID_CP_SEC_DISPLAY);
|
||||
if (!ret) {
|
||||
smmu_state->state = ATTACHED;
|
||||
smmu_state->secure_level = SDE_DRM_SEC_NON_SEC;
|
||||
@@ -503,7 +537,9 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
|
||||
break;
|
||||
|
||||
case ATTACH_SEC_REQ:
|
||||
ret = _sde_kms_attach_sec_cb(sde_kms, VMID_CP_PIXEL);
|
||||
vmid = (smmu_state->secure_level == SDE_DRM_SEC_ONLY) ?
|
||||
VMID_CP_SEC_DISPLAY : VMID_CP_CAMERA_PREVIEW;
|
||||
ret = _sde_kms_attach_sec_cb(sde_kms, VMID_CP_PIXEL, vmid);
|
||||
if (!ret) {
|
||||
smmu_state->state = ATTACHED;
|
||||
smmu_state->secure_level = SDE_DRM_SEC_NON_SEC;
|
||||
@@ -527,29 +563,34 @@ static int _sde_kms_secure_ctrl(struct sde_kms *sde_kms, struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
end:
|
||||
smmu_state->sui_misr_state = NONE;
|
||||
smmu_state->transition_type = NONE;
|
||||
smmu_state->transition_error = false;
|
||||
|
||||
/*
|
||||
* If switch failed, toggling secure_level is enough since
|
||||
* there are only two secure levels - secure/non-secure
|
||||
*/
|
||||
if (ret) {
|
||||
smmu_state->transition_error = true;
|
||||
SDE_ERROR(
|
||||
"crtc%d: req_state %d, new_state %d, sec_lvl %d, ret %d\n",
|
||||
DRMID(crtc), old_smmu_state, smmu_state->state,
|
||||
smmu_state->secure_level, ret);
|
||||
|
||||
smmu_state->state = smmu_state->prev_state;
|
||||
smmu_state->secure_level = !smmu_state->secure_level;
|
||||
smmu_state->secure_level = smmu_state->prev_secure_level;
|
||||
|
||||
if (smmu_state->sui_misr_state == SUI_MISR_ENABLE_REQ)
|
||||
_sde_kms_sui_misr_ctrl(sde_kms, crtc, false);
|
||||
}
|
||||
|
||||
SDE_DEBUG(
|
||||
"crtc %d: old_state %d, req_state %d, new_state %d, sec_lvl %d, ret %d\n",
|
||||
DRMID(crtc), smmu_state->prev_state, old_smmu_state,
|
||||
smmu_state->state, smmu_state->secure_level, ret);
|
||||
SDE_EVT32(DRMID(crtc), smmu_state->prev_state,
|
||||
smmu_state->state, smmu_state->transition_type,
|
||||
smmu_state->transition_error, smmu_state->secure_level,
|
||||
SDE_DEBUG("crtc %d: req_state %d, new_state %d, sec_lvl %d, ret %d\n",
|
||||
DRMID(crtc), old_smmu_state, smmu_state->state,
|
||||
smmu_state->secure_level, ret);
|
||||
SDE_EVT32(DRMID(crtc), smmu_state->state, smmu_state->prev_state,
|
||||
smmu_state->transition_type,
|
||||
smmu_state->transition_error,
|
||||
smmu_state->secure_level, smmu_state->prev_secure_level,
|
||||
smmu_state->sui_misr_state, ret, SDE_EVTLOG_FUNC_EXIT);
|
||||
|
||||
smmu_state->sui_misr_state = NONE;
|
||||
smmu_state->transition_type = NONE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -565,6 +606,7 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms,
|
||||
struct drm_device *dev = sde_kms->dev;
|
||||
int i, ops = 0, ret = 0;
|
||||
bool old_valid_fb = false;
|
||||
struct sde_kms_smmu_state_data *smmu_state = &sde_kms->smmu_state;
|
||||
|
||||
for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
|
||||
if (!crtc->state || !crtc->state->active)
|
||||
@@ -601,8 +643,10 @@ static int sde_kms_prepare_secure_transition(struct msm_kms *kms,
|
||||
return ops;
|
||||
}
|
||||
|
||||
if (!ops)
|
||||
if (!ops) {
|
||||
smmu_state->transition_error = false;
|
||||
goto no_ops;
|
||||
}
|
||||
|
||||
SDE_DEBUG("%d:secure operations(%x) started on state:%pK\n",
|
||||
crtc->base.id, ops, crtc->state);
|
||||
|
Reference in New Issue
Block a user