disp: msm: make kms a DRM client for lastclose logic
Since some APIs previously used during lastclose are no longer exposed to drivers (__drm_atomic_helper_disable_plane, and __drm_atomic_helper_set_config), make kms a DRM client and use the drm_client_modeset_commit_force API to do lastclose cleanup. Change-Id: I543392fe79558a3996e326a0f222793c56d71e4f Signed-off-by: Steve Cohen <cohens@codeaurora.org>
This commit is contained in:
134
msm/msm_drv.c
134
msm/msm_drv.c
@@ -813,6 +813,18 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
|
|||||||
priv->fbdev = msm_fbdev_init(ddev);
|
priv->fbdev = msm_fbdev_init(ddev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* create drm client only when fbdev is not supported */
|
||||||
|
if (!priv->fbdev) {
|
||||||
|
ret = drm_client_init(ddev, &kms->client, "kms_client", NULL);
|
||||||
|
if (ret) {
|
||||||
|
DRM_ERROR("failed to init kms_client: %d\n", ret);
|
||||||
|
kms->client.dev = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
drm_client_register(&kms->client);
|
||||||
|
}
|
||||||
|
|
||||||
priv->debug_root = debugfs_create_dir("debug",
|
priv->debug_root = debugfs_create_dir("debug",
|
||||||
ddev->primary->debugfs_root);
|
ddev->primary->debugfs_root);
|
||||||
if (IS_ERR_OR_NULL(priv->debug_root)) {
|
if (IS_ERR_OR_NULL(priv->debug_root)) {
|
||||||
@@ -928,101 +940,10 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
|
|||||||
context_close(ctx);
|
context_close(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msm_disable_all_modes_commit(
|
|
||||||
struct drm_device *dev,
|
|
||||||
struct drm_atomic_state *state)
|
|
||||||
{
|
|
||||||
struct drm_plane *plane;
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
unsigned int plane_mask;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
plane_mask = 0;
|
|
||||||
drm_for_each_plane(plane, dev) {
|
|
||||||
struct drm_plane_state *plane_state;
|
|
||||||
|
|
||||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
|
||||||
if (IS_ERR(plane_state)) {
|
|
||||||
ret = PTR_ERR(plane_state);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
plane_state->rotation = 0;
|
|
||||||
|
|
||||||
plane->old_fb = plane->fb;
|
|
||||||
plane_mask |= 1 << drm_plane_index(plane);
|
|
||||||
|
|
||||||
/* disable non-primary: */
|
|
||||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
DRM_DEBUG("disabling plane %d\n", plane->base.id);
|
|
||||||
|
|
||||||
ret = __drm_atomic_helper_disable_plane(plane, plane_state);
|
|
||||||
if (ret != 0)
|
|
||||||
DRM_ERROR("error %d disabling plane %d\n", ret,
|
|
||||||
plane->base.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
drm_for_each_crtc(crtc, dev) {
|
|
||||||
struct drm_mode_set mode_set;
|
|
||||||
|
|
||||||
memset(&mode_set, 0, sizeof(struct drm_mode_set));
|
|
||||||
mode_set.crtc = crtc;
|
|
||||||
|
|
||||||
DRM_DEBUG("disabling crtc %d\n", crtc->base.id);
|
|
||||||
|
|
||||||
ret = __drm_atomic_helper_set_config(&mode_set, state);
|
|
||||||
if (ret != 0)
|
|
||||||
DRM_ERROR("error %d disabling crtc %d\n", ret,
|
|
||||||
crtc->base.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
DRM_DEBUG("committing disables\n");
|
|
||||||
ret = drm_atomic_commit(state);
|
|
||||||
|
|
||||||
fail:
|
|
||||||
DRM_DEBUG("disables result %d\n", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* msm_clear_all_modes - disables all planes and crtcs via an atomic commit
|
|
||||||
* based on restore_fbdev_mode_atomic in drm_fb_helper.c
|
|
||||||
* @dev: device pointer
|
|
||||||
* @Return: 0 on success, otherwise -error
|
|
||||||
*/
|
|
||||||
static int msm_disable_all_modes(
|
|
||||||
struct drm_device *dev,
|
|
||||||
struct drm_modeset_acquire_ctx *ctx)
|
|
||||||
{
|
|
||||||
struct drm_atomic_state *state;
|
|
||||||
int ret, i;
|
|
||||||
|
|
||||||
state = drm_atomic_state_alloc(dev);
|
|
||||||
if (!state)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
state->acquire_ctx = ctx;
|
|
||||||
|
|
||||||
for (i = 0; i < TEARDOWN_DEADLOCK_RETRY_MAX; i++) {
|
|
||||||
ret = msm_disable_all_modes_commit(dev, state);
|
|
||||||
if (ret != -EDEADLK || ret != -ERESTARTSYS)
|
|
||||||
break;
|
|
||||||
drm_atomic_state_clear(state);
|
|
||||||
drm_modeset_backoff(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
drm_atomic_state_put(state);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void msm_lastclose(struct drm_device *dev)
|
static void msm_lastclose(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv = dev->dev_private;
|
struct msm_drm_private *priv = dev->dev_private;
|
||||||
struct msm_kms *kms = priv->kms;
|
struct msm_kms *kms = priv->kms;
|
||||||
struct drm_modeset_acquire_ctx ctx;
|
|
||||||
int i, rc;
|
int i, rc;
|
||||||
|
|
||||||
/* check for splash status before triggering cleanup
|
/* check for splash status before triggering cleanup
|
||||||
@@ -1048,32 +969,17 @@ static void msm_lastclose(struct drm_device *dev)
|
|||||||
flush_workqueue(priv->wq);
|
flush_workqueue(priv->wq);
|
||||||
|
|
||||||
if (priv->fbdev) {
|
if (priv->fbdev) {
|
||||||
drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
|
rc = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
|
||||||
return;
|
if (rc)
|
||||||
|
DRM_ERROR("restore FBDEV mode failed: %d\n", rc);
|
||||||
|
} else if (kms->client.dev) {
|
||||||
|
rc = drm_client_modeset_commit_force(&kms->client);
|
||||||
|
if (rc)
|
||||||
|
DRM_ERROR("client modeset commit failed: %d\n", rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_modeset_acquire_init(&ctx, 0);
|
|
||||||
retry:
|
|
||||||
rc = drm_modeset_lock_all_ctx(dev, &ctx);
|
|
||||||
if (rc)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
rc = msm_disable_all_modes(dev, &ctx);
|
|
||||||
if (rc)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (kms && kms->funcs && kms->funcs->lastclose)
|
if (kms && kms->funcs && kms->funcs->lastclose)
|
||||||
kms->funcs->lastclose(kms, &ctx);
|
kms->funcs->lastclose(kms);
|
||||||
|
|
||||||
fail:
|
|
||||||
if (rc == -EDEADLK) {
|
|
||||||
drm_modeset_backoff(&ctx);
|
|
||||||
goto retry;
|
|
||||||
} else if (rc) {
|
|
||||||
pr_err("last close failed: %d\n", rc);
|
|
||||||
}
|
|
||||||
drm_modeset_drop_locks(&ctx);
|
|
||||||
drm_modeset_acquire_fini(&ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t msm_irq(int irq, void *arg)
|
static irqreturn_t msm_irq(int irq, void *arg)
|
||||||
|
@@ -95,8 +95,7 @@ struct msm_kms_funcs {
|
|||||||
void (*postopen)(struct msm_kms *kms, struct drm_file *file);
|
void (*postopen)(struct msm_kms *kms, struct drm_file *file);
|
||||||
void (*preclose)(struct msm_kms *kms, struct drm_file *file);
|
void (*preclose)(struct msm_kms *kms, struct drm_file *file);
|
||||||
void (*postclose)(struct msm_kms *kms, struct drm_file *file);
|
void (*postclose)(struct msm_kms *kms, struct drm_file *file);
|
||||||
void (*lastclose)(struct msm_kms *kms,
|
void (*lastclose)(struct msm_kms *kms);
|
||||||
struct drm_modeset_acquire_ctx *ctx);
|
|
||||||
int (*register_events)(struct msm_kms *kms,
|
int (*register_events)(struct msm_kms *kms,
|
||||||
struct drm_mode_object *obj, u32 event, bool en);
|
struct drm_mode_object *obj, u32 event, bool en);
|
||||||
void (*set_encoder_mode)(struct msm_kms *kms,
|
void (*set_encoder_mode)(struct msm_kms *kms,
|
||||||
@@ -136,6 +135,9 @@ struct msm_kms {
|
|||||||
|
|
||||||
/* mapper-id used to request GEM buffer mapped for scanout: */
|
/* mapper-id used to request GEM buffer mapped for scanout: */
|
||||||
struct msm_gem_address_space *aspace;
|
struct msm_gem_address_space *aspace;
|
||||||
|
|
||||||
|
/* DRM client used for lastclose cleanup */
|
||||||
|
struct drm_client_dev client;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2068,13 +2068,13 @@ static int _sde_kms_helper_reset_custom_properties(struct sde_kms *sde_kms,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_kms_lastclose(struct msm_kms *kms,
|
static void sde_kms_lastclose(struct msm_kms *kms)
|
||||||
struct drm_modeset_acquire_ctx *ctx)
|
|
||||||
{
|
{
|
||||||
struct sde_kms *sde_kms;
|
struct sde_kms *sde_kms;
|
||||||
struct drm_device *dev;
|
struct drm_device *dev;
|
||||||
struct drm_atomic_state *state;
|
struct drm_atomic_state *state;
|
||||||
int ret, i;
|
struct drm_modeset_acquire_ctx ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!kms) {
|
if (!kms) {
|
||||||
SDE_ERROR("invalid argument\n");
|
SDE_ERROR("invalid argument\n");
|
||||||
@@ -2083,32 +2083,45 @@ static void sde_kms_lastclose(struct msm_kms *kms,
|
|||||||
|
|
||||||
sde_kms = to_sde_kms(kms);
|
sde_kms = to_sde_kms(kms);
|
||||||
dev = sde_kms->dev;
|
dev = sde_kms->dev;
|
||||||
|
drm_modeset_acquire_init(&ctx, 0);
|
||||||
|
|
||||||
state = drm_atomic_state_alloc(dev);
|
state = drm_atomic_state_alloc(dev);
|
||||||
if (!state)
|
if (!state) {
|
||||||
return;
|
ret = -ENOMEM;
|
||||||
|
goto out_ctx;
|
||||||
state->acquire_ctx = ctx;
|
|
||||||
|
|
||||||
for (i = 0; i < TEARDOWN_DEADLOCK_RETRY_MAX; i++) {
|
|
||||||
/* add reset of custom properties to the state */
|
|
||||||
ret = _sde_kms_helper_reset_custom_properties(sde_kms, state);
|
|
||||||
if (ret)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ret = drm_atomic_commit(state);
|
|
||||||
if (ret != -EDEADLK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
drm_atomic_state_clear(state);
|
|
||||||
drm_modeset_backoff(ctx);
|
|
||||||
SDE_DEBUG("deadlock backoff on attempt %d\n", i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->acquire_ctx = &ctx;
|
||||||
|
|
||||||
|
retry:
|
||||||
|
ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||||
if (ret)
|
if (ret)
|
||||||
SDE_ERROR("failed to run last close: %d\n", ret);
|
goto out_state;
|
||||||
|
|
||||||
|
ret = _sde_kms_helper_reset_custom_properties(sde_kms, state);
|
||||||
|
if (ret)
|
||||||
|
goto out_state;
|
||||||
|
|
||||||
|
ret = drm_atomic_commit(state);
|
||||||
|
out_state:
|
||||||
|
if (ret == -EDEADLK)
|
||||||
|
goto backoff;
|
||||||
|
|
||||||
drm_atomic_state_put(state);
|
drm_atomic_state_put(state);
|
||||||
|
out_ctx:
|
||||||
|
drm_modeset_drop_locks(&ctx);
|
||||||
|
drm_modeset_acquire_fini(&ctx);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
SDE_ERROR("kms lastclose failed: %d\n", ret);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
backoff:
|
||||||
|
drm_atomic_state_clear(state);
|
||||||
|
drm_modeset_backoff(&ctx);
|
||||||
|
|
||||||
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sde_kms_check_secure_transition(struct msm_kms *kms,
|
static int sde_kms_check_secure_transition(struct msm_kms *kms,
|
||||||
|
Reference in New Issue
Block a user