From ff5365a1e0c7a8f1068f9b1c2b1d6b98d0f1196c Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Tue, 19 Nov 2019 13:55:37 -0500 Subject: [PATCH 1/2] 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 --- msm/msm_drv.c | 134 +++++++--------------------------------------- msm/msm_kms.h | 6 ++- msm/sde/sde_kms.c | 57 ++++++++++++-------- 3 files changed, 59 insertions(+), 138 deletions(-) diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 20886e27e31d..dd248a9788ea 100644 --- a/msm/msm_drv.c +++ b/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); #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", ddev->primary->debugfs_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); } -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) { struct msm_drm_private *priv = dev->dev_private; struct msm_kms *kms = priv->kms; - struct drm_modeset_acquire_ctx ctx; int i, rc; /* check for splash status before triggering cleanup @@ -1048,32 +969,17 @@ static void msm_lastclose(struct drm_device *dev) flush_workqueue(priv->wq); if (priv->fbdev) { - drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); - return; + rc = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); + 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) - kms->funcs->lastclose(kms, &ctx); - -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); + kms->funcs->lastclose(kms); } static irqreturn_t msm_irq(int irq, void *arg) diff --git a/msm/msm_kms.h b/msm/msm_kms.h index 961018c6df57..02b9bae7766a 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -95,8 +95,7 @@ struct msm_kms_funcs { 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 (*lastclose)(struct msm_kms *kms, - struct drm_modeset_acquire_ctx *ctx); + void (*lastclose)(struct msm_kms *kms); int (*register_events)(struct msm_kms *kms, struct drm_mode_object *obj, u32 event, bool en); 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: */ struct msm_gem_address_space *aspace; + + /* DRM client used for lastclose cleanup */ + struct drm_client_dev client; }; /** diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index b337eda5c6f3..7e2bed7386bf 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -2068,13 +2068,13 @@ static int _sde_kms_helper_reset_custom_properties(struct sde_kms *sde_kms, return ret; } -static void sde_kms_lastclose(struct msm_kms *kms, - struct drm_modeset_acquire_ctx *ctx) +static void sde_kms_lastclose(struct msm_kms *kms) { struct sde_kms *sde_kms; struct drm_device *dev; struct drm_atomic_state *state; - int ret, i; + struct drm_modeset_acquire_ctx ctx; + int ret; if (!kms) { SDE_ERROR("invalid argument\n"); @@ -2083,32 +2083,45 @@ static void sde_kms_lastclose(struct msm_kms *kms, sde_kms = to_sde_kms(kms); dev = sde_kms->dev; + drm_modeset_acquire_init(&ctx, 0); state = drm_atomic_state_alloc(dev); - if (!state) - return; - - 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); + if (!state) { + ret = -ENOMEM; + goto out_ctx; } + state->acquire_ctx = &ctx; + +retry: + ret = drm_modeset_lock_all_ctx(dev, &ctx); 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); +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, From ae2dceb0b690ee2a0e9b10a6a7118f9ce1723472 Mon Sep 17 00:00:00 2001 From: Steve Cohen Date: Wed, 20 Nov 2019 18:37:11 -0500 Subject: [PATCH 2/2] disp: msm: sde: remove all preclose logic The DRM framework only calls the driver's preclose callback function if the LEGACY driver feature is enabled. Therefore strip out this logic as it never gets executed since LEGACY is not supported for msm_drm driver. Change-Id: I95474cd5424423ef194faae12f1241698f3e467e Signed-off-by: Steve Cohen --- msm/msm_drv.c | 10 ---- msm/msm_kms.h | 1 - msm/sde/sde_kms.c | 136 ---------------------------------------------- 3 files changed, 147 deletions(-) diff --git a/msm/msm_drv.c b/msm/msm_drv.c index dd248a9788ea..845982ff9819 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -907,15 +907,6 @@ static void context_close(struct msm_file_private *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) { struct msm_drm_private *priv = dev->dev_private; @@ -1564,7 +1555,6 @@ static struct drm_driver msm_driver = { DRIVER_ATOMIC | DRIVER_MODESET, .open = msm_open, - .preclose = msm_preclose, .postclose = msm_postclose, .lastclose = msm_lastclose, .irq_handler = msm_irq, diff --git a/msm/msm_kms.h b/msm/msm_kms.h index 02b9bae7766a..84e4da17a11d 100644 --- a/msm/msm_kms.h +++ b/msm/msm_kms.h @@ -93,7 +93,6 @@ struct msm_kms_funcs { struct drm_encoder *slave_encoder, bool is_cmd_mode); 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 (*lastclose)(struct msm_kms *kms); int (*register_events)(struct msm_kms *kms, diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 7e2bed7386bf..b96254ec802a 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1863,141 +1863,6 @@ static void sde_kms_destroy(struct msm_kms *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, struct drm_atomic_state *state) { @@ -2895,7 +2760,6 @@ static const struct msm_kms_funcs kms_funcs = { .irq_postinstall = sde_irq_postinstall, .irq_uninstall = sde_irq_uninstall, .irq = sde_irq, - .preclose = sde_kms_preclose, .lastclose = sde_kms_lastclose, .prepare_fence = sde_kms_prepare_fence, .prepare_commit = sde_kms_prepare_commit,