Merge changes I95474cd5,I543392fe into display-kernel.lnx.1.0

* changes:
  disp: msm: sde: remove all preclose logic
  disp: msm: make kms a DRM client for lastclose logic
This commit is contained in:
Linux Build Service Account
2019-12-09 12:26:54 -08:00
committed by Gerrit - the friendly Code Review server
3 changed files with 59 additions and 285 deletions

View File

@@ -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)) {
@@ -895,15 +907,6 @@ static void context_close(struct msm_file_private *ctx)
kfree(ctx); kfree(ctx);
} }
static void msm_preclose(struct drm_device *dev, struct drm_file *file)
{
struct msm_drm_private *priv = dev->dev_private;
struct msm_kms *kms = priv->kms;
if (kms && kms->funcs && kms->funcs->preclose)
kms->funcs->preclose(kms, file);
}
static void msm_postclose(struct drm_device *dev, struct drm_file *file) static void msm_postclose(struct drm_device *dev, struct drm_file *file)
{ {
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
@@ -928,101 +931,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 +960,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)
@@ -1658,7 +1555,6 @@ static struct drm_driver msm_driver = {
DRIVER_ATOMIC | DRIVER_ATOMIC |
DRIVER_MODESET, DRIVER_MODESET,
.open = msm_open, .open = msm_open,
.preclose = msm_preclose,
.postclose = msm_postclose, .postclose = msm_postclose,
.lastclose = msm_lastclose, .lastclose = msm_lastclose,
.irq_handler = msm_irq, .irq_handler = msm_irq,

View File

@@ -93,10 +93,8 @@ struct msm_kms_funcs {
struct drm_encoder *slave_encoder, struct drm_encoder *slave_encoder,
bool is_cmd_mode); bool is_cmd_mode);
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 (*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 +134,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;
}; };
/** /**

View File

@@ -1867,141 +1867,6 @@ static void sde_kms_destroy(struct msm_kms *kms)
kfree(sde_kms); kfree(sde_kms);
} }
static void _sde_kms_plane_force_remove(struct drm_plane *plane,
struct drm_atomic_state *state)
{
struct drm_plane_state *plane_state;
int ret = 0;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
SDE_ERROR("error %d getting plane %d state\n",
ret, plane->base.id);
return;
}
plane->old_fb = plane->fb;
SDE_DEBUG("disabling plane %d\n", plane->base.id);
ret = __drm_atomic_helper_disable_plane(plane, plane_state);
if (ret != 0)
SDE_ERROR("error %d disabling plane %d\n", ret,
plane->base.id);
}
static int _sde_kms_remove_fbs(struct sde_kms *sde_kms, struct drm_file *file,
struct drm_atomic_state *state)
{
struct drm_device *dev = sde_kms->dev;
struct drm_framebuffer *fb, *tfb;
struct list_head fbs;
struct drm_plane *plane;
int ret = 0;
u32 plane_mask = 0;
INIT_LIST_HEAD(&fbs);
list_for_each_entry_safe(fb, tfb, &file->fbs, filp_head) {
if (drm_framebuffer_read_refcount(fb) > 1) {
list_move_tail(&fb->filp_head, &fbs);
drm_for_each_plane(plane, dev) {
if (plane->fb == fb) {
plane_mask |=
1 << drm_plane_index(plane);
_sde_kms_plane_force_remove(
plane, state);
}
}
} else {
list_del_init(&fb->filp_head);
drm_framebuffer_put(fb);
}
}
if (list_empty(&fbs)) {
SDE_DEBUG("skip commit as no fb(s)\n");
drm_atomic_state_put(state);
return 0;
}
SDE_DEBUG("committing after removing all the pipes\n");
ret = drm_atomic_commit(state);
if (ret) {
/*
* move the fbs back to original list, so it would be
* handled during drm_release
*/
list_for_each_entry_safe(fb, tfb, &fbs, filp_head)
list_move_tail(&fb->filp_head, &file->fbs);
SDE_ERROR("atomic commit failed in preclose, ret:%d\n", ret);
goto end;
}
while (!list_empty(&fbs)) {
fb = list_first_entry(&fbs, typeof(*fb), filp_head);
list_del_init(&fb->filp_head);
drm_framebuffer_put(fb);
}
end:
return ret;
}
static void sde_kms_preclose(struct msm_kms *kms, struct drm_file *file)
{
struct sde_kms *sde_kms = to_sde_kms(kms);
struct drm_device *dev = sde_kms->dev;
struct msm_drm_private *priv = dev->dev_private;
unsigned int i;
struct drm_atomic_state *state = NULL;
struct drm_modeset_acquire_ctx ctx;
int ret = 0;
/* cancel pending flip event */
for (i = 0; i < priv->num_crtcs; i++)
sde_crtc_complete_flip(priv->crtcs[i], file);
drm_modeset_acquire_init(&ctx, 0);
retry:
ret = drm_modeset_lock_all_ctx(dev, &ctx);
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
goto retry;
} else if (WARN_ON(ret)) {
goto end;
}
state = drm_atomic_state_alloc(dev);
if (!state) {
ret = -ENOMEM;
goto end;
}
state->acquire_ctx = &ctx;
for (i = 0; i < TEARDOWN_DEADLOCK_RETRY_MAX; i++) {
ret = _sde_kms_remove_fbs(sde_kms, file, state);
if (ret != -EDEADLK)
break;
drm_atomic_state_clear(state);
drm_modeset_backoff(&ctx);
}
end:
if (state)
drm_atomic_state_put(state);
SDE_DEBUG("sde preclose done, ret:%d\n", ret);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
}
static int _sde_kms_helper_reset_custom_properties(struct sde_kms *sde_kms, static int _sde_kms_helper_reset_custom_properties(struct sde_kms *sde_kms,
struct drm_atomic_state *state) struct drm_atomic_state *state)
{ {
@@ -2072,13 +1937,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");
@@ -2087,32 +1952,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,
@@ -2886,7 +2764,6 @@ static const struct msm_kms_funcs kms_funcs = {
.irq_postinstall = sde_irq_postinstall, .irq_postinstall = sde_irq_postinstall,
.irq_uninstall = sde_irq_uninstall, .irq_uninstall = sde_irq_uninstall,
.irq = sde_irq, .irq = sde_irq,
.preclose = sde_kms_preclose,
.lastclose = sde_kms_lastclose, .lastclose = sde_kms_lastclose,
.prepare_fence = sde_kms_prepare_fence, .prepare_fence = sde_kms_prepare_fence,
.prepare_commit = sde_kms_prepare_commit, .prepare_commit = sde_kms_prepare_commit,