Merge "disp: msm: sde: add helper to check VM hw availability"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
bb36f9fd40
@@ -1645,6 +1645,7 @@ int msm_ioctl_display_hint_ops(struct drm_device *dev, void *data,
|
|||||||
|
|
||||||
SDE_EVT32(display_hint->hint_flags);
|
SDE_EVT32(display_hint->hint_flags);
|
||||||
|
|
||||||
|
/* Any new hint added will require a check for VM ownership before HW is accessed */
|
||||||
if (display_hint->hint_flags == DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT) {
|
if (display_hint->hint_flags == DRM_MSM_DISPLAY_EARLY_WAKEUP_HINT) {
|
||||||
if (!display_hint->data) {
|
if (!display_hint->data) {
|
||||||
DRM_ERROR("early_wakeup: wrong parameter\n");
|
DRM_ERROR("early_wakeup: wrong parameter\n");
|
||||||
|
@@ -131,7 +131,6 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
|
|||||||
struct drm_event event;
|
struct drm_event event;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
|
|
||||||
sde_kms = _sde_connector_get_kms(&c_conn->base);
|
sde_kms = _sde_connector_get_kms(&c_conn->base);
|
||||||
if (!sde_kms) {
|
if (!sde_kms) {
|
||||||
@@ -167,8 +166,7 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
|
|||||||
|
|
||||||
sde_vm_lock(sde_kms);
|
sde_vm_lock(sde_kms);
|
||||||
|
|
||||||
vm_ops = sde_vm_get_ops(sde_kms);
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
if (vm_ops && vm_ops->vm_owns_hw && !vm_ops->vm_owns_hw(sde_kms)) {
|
|
||||||
SDE_DEBUG("skipping bl update due to HW unavailablity\n");
|
SDE_DEBUG("skipping bl update due to HW unavailablity\n");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@@ -2077,7 +2075,6 @@ static ssize_t _sde_debugfs_conn_cmd_tx_write(struct file *file,
|
|||||||
{
|
{
|
||||||
struct drm_connector *connector = file->private_data;
|
struct drm_connector *connector = file->private_data;
|
||||||
struct sde_connector *c_conn = NULL;
|
struct sde_connector *c_conn = NULL;
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
char *input, *token, *input_copy, *input_dup = NULL;
|
char *input, *token, *input_copy, *input_dup = NULL;
|
||||||
const char *delim = " ";
|
const char *delim = " ";
|
||||||
@@ -2107,9 +2104,8 @@ static ssize_t _sde_debugfs_conn_cmd_tx_write(struct file *file,
|
|||||||
if (!input)
|
if (!input)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
vm_ops = sde_vm_get_ops(sde_kms);
|
|
||||||
sde_vm_lock(sde_kms);
|
sde_vm_lock(sde_kms);
|
||||||
if (vm_ops && vm_ops->vm_owns_hw && !vm_ops->vm_owns_hw(sde_kms)) {
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
SDE_DEBUG("op not supported due to HW unavailablity\n");
|
SDE_DEBUG("op not supported due to HW unavailablity\n");
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
goto end;
|
goto end;
|
||||||
|
@@ -6470,7 +6470,6 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
|
|||||||
struct sde_crtc *sde_crtc;
|
struct sde_crtc *sde_crtc;
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct sde_crtc_mixer *m;
|
struct sde_crtc_mixer *m;
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
int i = 0, rc;
|
int i = 0, rc;
|
||||||
ssize_t len = 0;
|
ssize_t len = 0;
|
||||||
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
||||||
@@ -6491,9 +6490,8 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
vm_ops = sde_vm_get_ops(sde_kms);
|
|
||||||
sde_vm_lock(sde_kms);
|
sde_vm_lock(sde_kms);
|
||||||
if (vm_ops && vm_ops->vm_owns_hw && !vm_ops->vm_owns_hw(sde_kms)) {
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
SDE_DEBUG("op not supported due to HW unavailability\n");
|
SDE_DEBUG("op not supported due to HW unavailability\n");
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
goto end;
|
goto end;
|
||||||
|
@@ -4040,9 +4040,13 @@ static void sde_encoder_early_wakeup_work_handler(struct kthread_work *work)
|
|||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc = container_of(work,
|
struct sde_encoder_virt *sde_enc = container_of(work,
|
||||||
struct sde_encoder_virt, early_wakeup_work);
|
struct sde_encoder_virt, early_wakeup_work);
|
||||||
|
struct sde_kms *sde_kms = to_sde_kms(ddev_to_msm_kms(sde_enc->base.dev));
|
||||||
|
|
||||||
if (!sde_enc) {
|
sde_vm_lock(sde_kms);
|
||||||
SDE_ERROR("invalid sde encoder\n");
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
|
sde_vm_unlock(sde_kms);
|
||||||
|
SDE_DEBUG("skip early wakeup for ENC-%d, HW is owned by other VM\n",
|
||||||
|
DRMID(&sde_enc->base));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4050,6 +4054,7 @@ static void sde_encoder_early_wakeup_work_handler(struct kthread_work *work)
|
|||||||
sde_encoder_resource_control(&sde_enc->base,
|
sde_encoder_resource_control(&sde_enc->base,
|
||||||
SDE_ENC_RC_EVENT_EARLY_WAKEUP);
|
SDE_ENC_RC_EVENT_EARLY_WAKEUP);
|
||||||
SDE_ATRACE_END("encoder_early_wakeup");
|
SDE_ATRACE_END("encoder_early_wakeup");
|
||||||
|
sde_vm_unlock(sde_kms);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sde_encoder_early_wakeup(struct drm_encoder *drm_enc)
|
void sde_encoder_early_wakeup(struct drm_encoder *drm_enc)
|
||||||
@@ -4764,7 +4769,6 @@ static ssize_t _sde_encoder_misr_read(struct file *file,
|
|||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
struct sde_kms *sde_kms = NULL;
|
struct sde_kms *sde_kms = NULL;
|
||||||
struct drm_encoder *drm_enc;
|
struct drm_encoder *drm_enc;
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
int i = 0, len = 0;
|
int i = 0, len = 0;
|
||||||
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
||||||
int rc;
|
int rc;
|
||||||
@@ -4790,9 +4794,8 @@ static ssize_t _sde_encoder_misr_read(struct file *file,
|
|||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
vm_ops = sde_vm_get_ops(sde_kms);
|
|
||||||
sde_vm_lock(sde_kms);
|
sde_vm_lock(sde_kms);
|
||||||
if (vm_ops && vm_ops->vm_owns_hw && !vm_ops->vm_owns_hw(sde_kms)) {
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
SDE_DEBUG("op not supported due to HW unavailablity\n");
|
SDE_DEBUG("op not supported due to HW unavailablity\n");
|
||||||
rc = -EOPNOTSUPP;
|
rc = -EOPNOTSUPP;
|
||||||
goto end;
|
goto end;
|
||||||
|
@@ -2765,6 +2765,7 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
|
|||||||
enum sde_crtc_vm_req old_vm_req = VM_REQ_NONE, new_vm_req = VM_REQ_NONE;
|
enum sde_crtc_vm_req old_vm_req = VM_REQ_NONE, new_vm_req = VM_REQ_NONE;
|
||||||
struct sde_vm_ops *vm_ops;
|
struct sde_vm_ops *vm_ops;
|
||||||
bool vm_req_active = false;
|
bool vm_req_active = false;
|
||||||
|
bool vm_owns_hw;
|
||||||
enum sde_crtc_idle_pc_state idle_pc_state;
|
enum sde_crtc_idle_pc_state idle_pc_state;
|
||||||
struct sde_mdss_cfg *catalog;
|
struct sde_mdss_cfg *catalog;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -2789,7 +2790,7 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sde_vm_lock(sde_kms);
|
sde_vm_lock(sde_kms);
|
||||||
|
vm_owns_hw = sde_vm_owns_hw(sde_kms);
|
||||||
for_each_oldnew_crtc_in_state(state, crtc, old_cstate, new_cstate, i) {
|
for_each_oldnew_crtc_in_state(state, crtc, old_cstate, new_cstate, i) {
|
||||||
struct sde_crtc_state *old_state = NULL, *new_state = NULL;
|
struct sde_crtc_state *old_state = NULL, *new_state = NULL;
|
||||||
|
|
||||||
@@ -2814,8 +2815,7 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
|
|||||||
if (rc) {
|
if (rc) {
|
||||||
SDE_ERROR(
|
SDE_ERROR(
|
||||||
"VM transition check failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
|
"VM transition check failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
|
||||||
old_vm_req, new_vm_req,
|
old_vm_req, new_vm_req, vm_owns_hw, rc);
|
||||||
vm_ops->vm_owns_hw(sde_kms), rc);
|
|
||||||
goto end;
|
goto end;
|
||||||
} else if (old_vm_req == VM_REQ_ACQUIRE &&
|
} else if (old_vm_req == VM_REQ_ACQUIRE &&
|
||||||
new_vm_req == VM_REQ_NONE) {
|
new_vm_req == VM_REQ_NONE) {
|
||||||
@@ -2852,9 +2852,8 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
|
|||||||
crtc_encoder_cnt++;
|
crtc_encoder_cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDE_EVT32(old_vm_req, new_vm_req, vm_ops->vm_owns_hw(sde_kms));
|
SDE_EVT32(old_vm_req, new_vm_req, vm_owns_hw);
|
||||||
SDE_DEBUG("VM o_state:%d, n_state:%d, hw_owner:%d\n", old_vm_req,
|
SDE_DEBUG("VM o_state:%d, n_state:%d, hw_owner:%d\n", old_vm_req, new_vm_req, vm_owns_hw);
|
||||||
new_vm_req, vm_ops->vm_owns_hw(sde_kms));
|
|
||||||
|
|
||||||
for_each_new_connector_in_state(state, connector, new_connstate, i) {
|
for_each_new_connector_in_state(state, connector, new_connstate, i) {
|
||||||
int conn_mask = active_cstate->connector_mask;
|
int conn_mask = active_cstate->connector_mask;
|
||||||
@@ -2903,13 +2902,12 @@ static int sde_kms_check_vm_request(struct msm_kms *kms,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((new_vm_req == VM_REQ_ACQUIRE) && !vm_ops->vm_owns_hw(sde_kms)) {
|
if ((new_vm_req == VM_REQ_ACQUIRE) && !vm_owns_hw) {
|
||||||
rc = vm_ops->vm_acquire(sde_kms);
|
rc = vm_ops->vm_acquire(sde_kms);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SDE_ERROR(
|
SDE_ERROR(
|
||||||
"VM acquire failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
|
"VM acquire failed; o_state:%d, n_state:%d, hw_owner:%d, rc:%d\n",
|
||||||
old_vm_req, new_vm_req,
|
old_vm_req, new_vm_req, vm_owns_hw, rc);
|
||||||
vm_ops->vm_owns_hw(sde_kms), rc);
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5062,10 +5060,9 @@ static int _sde_kms_register_events(struct msm_kms *kms,
|
|||||||
struct drm_mode_object *obj, u32 event, bool en)
|
struct drm_mode_object *obj, u32 event, bool en)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct drm_crtc *crtc = NULL;
|
struct drm_crtc *crtc;
|
||||||
struct drm_connector *conn = NULL;
|
struct drm_connector *conn;
|
||||||
struct sde_kms *sde_kms = NULL;
|
struct sde_kms *sde_kms;
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
|
|
||||||
if (!kms || !obj) {
|
if (!kms || !obj) {
|
||||||
SDE_ERROR("invalid argument kms %pK obj %pK\n", kms, obj);
|
SDE_ERROR("invalid argument kms %pK obj %pK\n", kms, obj);
|
||||||
@@ -5073,24 +5070,18 @@ static int _sde_kms_register_events(struct msm_kms *kms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sde_kms = to_sde_kms(kms);
|
sde_kms = to_sde_kms(kms);
|
||||||
|
sde_vm_lock(sde_kms);
|
||||||
|
if (!sde_vm_owns_hw(sde_kms)) {
|
||||||
|
sde_vm_unlock(sde_kms);
|
||||||
|
SDE_DEBUG("HW is owned by other VM\n");
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
|
||||||
/* check vm ownership, if event registration requires HW access */
|
/* check vm ownership, if event registration requires HW access */
|
||||||
switch (obj->type) {
|
switch (obj->type) {
|
||||||
case DRM_MODE_OBJECT_CRTC:
|
case DRM_MODE_OBJECT_CRTC:
|
||||||
vm_ops = sde_vm_get_ops(sde_kms);
|
|
||||||
sde_vm_lock(sde_kms);
|
|
||||||
|
|
||||||
if (vm_ops && vm_ops->vm_owns_hw
|
|
||||||
&& !vm_ops->vm_owns_hw(sde_kms)) {
|
|
||||||
sde_vm_unlock(sde_kms);
|
|
||||||
SDE_DEBUG("HW is owned by other VM\n");
|
|
||||||
return -EACCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
crtc = obj_to_crtc(obj);
|
crtc = obj_to_crtc(obj);
|
||||||
ret = sde_crtc_register_custom_event(sde_kms, crtc, event, en);
|
ret = sde_crtc_register_custom_event(sde_kms, crtc, event, en);
|
||||||
|
|
||||||
sde_vm_unlock(sde_kms);
|
|
||||||
break;
|
break;
|
||||||
case DRM_MODE_OBJECT_CONNECTOR:
|
case DRM_MODE_OBJECT_CONNECTOR:
|
||||||
conn = obj_to_connector(obj);
|
conn = obj_to_connector(obj);
|
||||||
@@ -5099,6 +5090,8 @@ static int _sde_kms_register_events(struct msm_kms *kms,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sde_vm_unlock(sde_kms);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SDE_VM_H__
|
#ifndef __SDE_VM_H__
|
||||||
@@ -285,6 +285,23 @@ static inline struct sde_vm_ops *sde_vm_get_ops(struct sde_kms *sde_kms)
|
|||||||
|
|
||||||
return &sde_kms->vm->vm_ops;
|
return &sde_kms->vm->vm_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_vm_owns_hw - checks if the executing VM currently has HW ownership (caller must be holding
|
||||||
|
* the sde_vm_lock)
|
||||||
|
* @sde_kms - pointer to sde_kms
|
||||||
|
* @return - true if this VM currently owns the HW
|
||||||
|
*/
|
||||||
|
static inline bool sde_vm_owns_hw(struct sde_kms *sde_kms)
|
||||||
|
{
|
||||||
|
struct sde_vm_ops *vm_ops = sde_kms ? sde_vm_get_ops(sde_kms) : NULL;
|
||||||
|
|
||||||
|
if (vm_ops && vm_ops->vm_owns_hw)
|
||||||
|
return vm_ops->vm_owns_hw(sde_kms);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
static inline int sde_vm_primary_init(struct sde_kms *kms)
|
static inline int sde_vm_primary_init(struct sde_kms *kms)
|
||||||
{
|
{
|
||||||
@@ -314,5 +331,10 @@ static inline struct sde_vm_ops *sde_vm_get_ops(struct sde_kms *sde_kms)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool sde_vm_owns_hw(struct sde_kms *sde_kms)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* IS_ENABLED(CONFIG_DRM_SDE_VM) */
|
#endif /* IS_ENABLED(CONFIG_DRM_SDE_VM) */
|
||||||
#endif /* __SDE_VM_H__ */
|
#endif /* __SDE_VM_H__ */
|
||||||
|
@@ -296,16 +296,13 @@ int sde_vm_request_valid(struct sde_kms *sde_kms,
|
|||||||
enum sde_crtc_vm_req old_state,
|
enum sde_crtc_vm_req old_state,
|
||||||
enum sde_crtc_vm_req new_state)
|
enum sde_crtc_vm_req new_state)
|
||||||
{
|
{
|
||||||
struct sde_vm_ops *vm_ops;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
bool vm_owns_hw = sde_vm_owns_hw(sde_kms);
|
||||||
vm_ops = &sde_kms->vm->vm_ops;
|
|
||||||
|
|
||||||
switch (new_state) {
|
switch (new_state) {
|
||||||
case VM_REQ_RELEASE:
|
case VM_REQ_RELEASE:
|
||||||
case VM_REQ_NONE:
|
case VM_REQ_NONE:
|
||||||
if ((old_state == VM_REQ_RELEASE) ||
|
if ((old_state == VM_REQ_RELEASE) || !vm_owns_hw)
|
||||||
!vm_ops->vm_owns_hw(sde_kms))
|
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
break;
|
break;
|
||||||
case VM_REQ_ACQUIRE:
|
case VM_REQ_ACQUIRE:
|
||||||
@@ -318,9 +315,8 @@ int sde_vm_request_valid(struct sde_kms *sde_kms,
|
|||||||
};
|
};
|
||||||
|
|
||||||
SDE_DEBUG("old req: %d new req: %d owns_hw: %d, rc: %d\n",
|
SDE_DEBUG("old req: %d new req: %d owns_hw: %d, rc: %d\n",
|
||||||
old_state, new_state,
|
old_state, new_state, vm_owns_hw, rc);
|
||||||
vm_ops->vm_owns_hw(sde_kms), rc);
|
SDE_EVT32(old_state, new_state, vm_owns_hw, rc);
|
||||||
SDE_EVT32(old_state, new_state, vm_ops->vm_owns_hw(sde_kms), rc);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user