diff --git a/msm/sde/sde_vm.h b/msm/sde/sde_vm.h index 366b116aadfe..1e7ae95de59d 100644 --- a/msm/sde/sde_vm.h +++ b/msm/sde/sde_vm.h @@ -119,6 +119,26 @@ struct sde_vm_ops { * @ops - primary VM specific ops functions */ void (*vm_deinit)(struct sde_kms *kms, struct sde_vm_ops *ops); + + /** + * vm_check - hook to check with vm_clients for its readiness to release + the HW reasources + */ + int (*vm_check)(void); + + /** + * vm_client_pre_release - hook to invoke vm_client list for pre_release + handling + * @kms - handle to sde_kms + */ + int (*vm_client_pre_release)(struct sde_kms *kms); + + /** + * vm_client_post_acquire - hook to invoke vm_client list for + * post_acquire resource handling + * @kms - handle to sde_kms + */ + int (*vm_client_post_acquire)(struct sde_kms *kms); }; /** diff --git a/msm/sde/sde_vm_common.c b/msm/sde/sde_vm_common.c index 5e59aa9af6de..0eac9a24cc5f 100644 --- a/msm/sde/sde_vm_common.c +++ b/msm/sde/sde_vm_common.c @@ -211,3 +211,79 @@ void sde_vm_free_resources(struct msm_io_res *io_res) msm_dss_clean_io_mem(&io_res->mem); msm_dss_clean_io_irq(&io_res->irq); } + +int sde_vm_post_acquire(struct sde_kms *kms) +{ + struct msm_drm_private *priv = kms->dev->dev_private; + struct msm_vm_client_entry *entry; + int rc = 0; + + list_for_each_entry(entry, &priv->vm_client_list, list) { + if (!entry->ops.vm_post_hw_acquire) + continue; + + rc = entry->ops.vm_post_hw_acquire(entry->data); + if (rc) { + SDE_ERROR("post_acquire failed for device: %d\n", + entry->dev->id); + goto post_acquire_rollback; + } + } + + return rc; + +post_acquire_rollback: + list_for_each_entry_continue_reverse(entry, &priv->vm_client_list, + list) { + if (!entry->ops.vm_pre_hw_release) + continue; + + rc = entry->ops.vm_pre_hw_release(entry->data); + if (rc) { + SDE_ERROR( + "post_acquire failed during rollback for device: %d\n", + entry->dev->id); + break; + } + } + + return rc; +} + +int sde_vm_pre_release(struct sde_kms *kms) +{ + struct msm_drm_private *priv = kms->dev->dev_private; + struct msm_vm_client_entry *entry; + int rc = 0; + + list_for_each_entry(entry, &priv->vm_client_list, list) { + if (!entry->ops.vm_pre_hw_release) + continue; + + rc = entry->ops.vm_pre_hw_release(entry->data); + if (rc) { + SDE_ERROR("pre_release failed for device: %d\n", + entry->dev->id); + goto pre_release_rollback; + } + } + + return rc; + +pre_release_rollback: + list_for_each_entry_continue_reverse(entry, &priv->vm_client_list, + list) { + if (!entry->ops.vm_post_hw_acquire) + continue; + + rc = entry->ops.vm_post_hw_acquire(entry->data); + if (rc) { + SDE_ERROR( + "post_acquire failed during rollback for device: %d\n", + entry->dev->id); + break; + } + } + + return rc; +} diff --git a/msm/sde/sde_vm_common.h b/msm/sde/sde_vm_common.h index ef9e389e5a2e..8914688be8ac 100644 --- a/msm/sde/sde_vm_common.h +++ b/msm/sde/sde_vm_common.h @@ -63,4 +63,16 @@ int sde_vm_get_resources(struct sde_kms *sde_kms, struct msm_io_res *io_res); */ void sde_vm_free_resources(struct msm_io_res *io_res); +/** + * sde_vm_post_acquire - handle post_acquire events with all the VM clients + * @kms: handle to sde_kms + */ +int sde_vm_post_acquire(struct sde_kms *kms); + +/** + * sde_vm_pre_release - handle pre_release events with all the VM clients + * @kms: handle to sde_kms + */ +int sde_vm_pre_release(struct sde_kms *kms); + #endif /* __SDE_VM_COMMON_H__ */ diff --git a/msm/sde/sde_vm_primary.c b/msm/sde/sde_vm_primary.c index 984917243c42..21544014e732 100644 --- a/msm/sde/sde_vm_primary.c +++ b/msm/sde/sde_vm_primary.c @@ -254,6 +254,8 @@ static void _sde_vm_set_ops(struct sde_vm_ops *ops) { memset(ops, 0, sizeof(*ops)); + ops->vm_client_pre_release = sde_vm_pre_release; + ops->vm_client_post_acquire = sde_vm_post_acquire; ops->vm_release = _sde_vm_release; ops->vm_owns_hw = sde_vm_owns_hw; ops->vm_deinit = _sde_vm_deinit; diff --git a/msm/sde/sde_vm_trusted.c b/msm/sde/sde_vm_trusted.c index 0f59e5145338..8a21593619d1 100644 --- a/msm/sde/sde_vm_trusted.c +++ b/msm/sde/sde_vm_trusted.c @@ -332,6 +332,8 @@ static void _sde_vm_set_ops(struct sde_vm_ops *ops) { memset(ops, 0, sizeof(*ops)); + ops->vm_client_pre_release = sde_vm_pre_release; + ops->vm_client_post_acquire = sde_vm_post_acquire; ops->vm_release = _sde_vm_release; ops->vm_owns_hw = sde_vm_owns_hw; ops->vm_deinit = _sde_vm_deinit;