diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2018-04-26 03:48:55 -0400 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2018-04-26 03:48:55 -0400 |
commit | 21fbd085e62ff9a11318f5a9aba55e56e8503173 (patch) | |
tree | 9c34947c4a95a21d0fd2e18eceed2924ef1c5cab | |
parent | bb1278e891662616ccf4584523318d5f7ddb3a7c (diff) |
drm/vmwgfx: Clean up fbdev modeset locking
At least since the atomic port, the vmwgfx fbdev code is taking
a number of unnecessary modeset locks. In particular the
kms_set_config() function will grab its own locks, leading to
locking retries. So avoid drm_modeset_lock_all() and instead
provide a local acquire context for kms_set_config(). Also have the
vmw_kms_fbdev_init data itself grab the lock that it needs.
This also fixed a long standing problem that vmw_fb_close() didn't
provide an acquire context for kms_set_config(), causing potential
warnings and hangs during driver unload. This problem was uncovered by the
recent commit "drm/vmwgfx: Improve on hibernation"
Testing done:
Repeated driver load and unload on Ubuntu 16.04.2
Fixes: c3b9b1657344 ("drm/vmwgfx: Improve on hibernation")
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Deepak Rawat <drawat@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 13 |
2 files changed, 20 insertions, 24 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 2582ffd36bb5..ba0cdb743c3e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | |||
@@ -441,11 +441,11 @@ static int vmwgfx_set_config_internal(struct drm_mode_set *set) | |||
441 | struct drm_crtc *crtc = set->crtc; | 441 | struct drm_crtc *crtc = set->crtc; |
442 | struct drm_framebuffer *fb; | 442 | struct drm_framebuffer *fb; |
443 | struct drm_crtc *tmp; | 443 | struct drm_crtc *tmp; |
444 | struct drm_modeset_acquire_ctx *ctx; | ||
445 | struct drm_device *dev = set->crtc->dev; | 444 | struct drm_device *dev = set->crtc->dev; |
445 | struct drm_modeset_acquire_ctx ctx; | ||
446 | int ret; | 446 | int ret; |
447 | 447 | ||
448 | ctx = dev->mode_config.acquire_ctx; | 448 | drm_modeset_acquire_init(&ctx, 0); |
449 | 449 | ||
450 | restart: | 450 | restart: |
451 | /* | 451 | /* |
@@ -458,7 +458,7 @@ restart: | |||
458 | 458 | ||
459 | fb = set->fb; | 459 | fb = set->fb; |
460 | 460 | ||
461 | ret = crtc->funcs->set_config(set, ctx); | 461 | ret = crtc->funcs->set_config(set, &ctx); |
462 | if (ret == 0) { | 462 | if (ret == 0) { |
463 | crtc->primary->crtc = crtc; | 463 | crtc->primary->crtc = crtc; |
464 | crtc->primary->fb = fb; | 464 | crtc->primary->fb = fb; |
@@ -473,20 +473,13 @@ restart: | |||
473 | } | 473 | } |
474 | 474 | ||
475 | if (ret == -EDEADLK) { | 475 | if (ret == -EDEADLK) { |
476 | dev->mode_config.acquire_ctx = NULL; | 476 | drm_modeset_backoff(&ctx); |
477 | |||
478 | retry_locking: | ||
479 | drm_modeset_backoff(ctx); | ||
480 | |||
481 | ret = drm_modeset_lock_all_ctx(dev, ctx); | ||
482 | if (ret) | ||
483 | goto retry_locking; | ||
484 | |||
485 | dev->mode_config.acquire_ctx = ctx; | ||
486 | |||
487 | goto restart; | 477 | goto restart; |
488 | } | 478 | } |
489 | 479 | ||
480 | drm_modeset_drop_locks(&ctx); | ||
481 | drm_modeset_acquire_fini(&ctx); | ||
482 | |||
490 | return ret; | 483 | return ret; |
491 | } | 484 | } |
492 | 485 | ||
@@ -624,7 +617,6 @@ static int vmw_fb_set_par(struct fb_info *info) | |||
624 | } | 617 | } |
625 | 618 | ||
626 | mutex_lock(&par->bo_mutex); | 619 | mutex_lock(&par->bo_mutex); |
627 | drm_modeset_lock_all(vmw_priv->dev); | ||
628 | ret = vmw_fb_kms_framebuffer(info); | 620 | ret = vmw_fb_kms_framebuffer(info); |
629 | if (ret) | 621 | if (ret) |
630 | goto out_unlock; | 622 | goto out_unlock; |
@@ -657,7 +649,6 @@ out_unlock: | |||
657 | drm_mode_destroy(vmw_priv->dev, old_mode); | 649 | drm_mode_destroy(vmw_priv->dev, old_mode); |
658 | par->set_mode = mode; | 650 | par->set_mode = mode; |
659 | 651 | ||
660 | drm_modeset_unlock_all(vmw_priv->dev); | ||
661 | mutex_unlock(&par->bo_mutex); | 652 | mutex_unlock(&par->bo_mutex); |
662 | 653 | ||
663 | return ret; | 654 | return ret; |
@@ -713,18 +704,14 @@ int vmw_fb_init(struct vmw_private *vmw_priv) | |||
713 | par->max_width = fb_width; | 704 | par->max_width = fb_width; |
714 | par->max_height = fb_height; | 705 | par->max_height = fb_height; |
715 | 706 | ||
716 | drm_modeset_lock_all(vmw_priv->dev); | ||
717 | ret = vmw_kms_fbdev_init_data(vmw_priv, 0, par->max_width, | 707 | ret = vmw_kms_fbdev_init_data(vmw_priv, 0, par->max_width, |
718 | par->max_height, &par->con, | 708 | par->max_height, &par->con, |
719 | &par->crtc, &init_mode); | 709 | &par->crtc, &init_mode); |
720 | if (ret) { | 710 | if (ret) |
721 | drm_modeset_unlock_all(vmw_priv->dev); | ||
722 | goto err_kms; | 711 | goto err_kms; |
723 | } | ||
724 | 712 | ||
725 | info->var.xres = init_mode->hdisplay; | 713 | info->var.xres = init_mode->hdisplay; |
726 | info->var.yres = init_mode->vdisplay; | 714 | info->var.yres = init_mode->vdisplay; |
727 | drm_modeset_unlock_all(vmw_priv->dev); | ||
728 | 715 | ||
729 | /* | 716 | /* |
730 | * Create buffers and alloc memory | 717 | * Create buffers and alloc memory |
@@ -832,7 +819,9 @@ int vmw_fb_close(struct vmw_private *vmw_priv) | |||
832 | cancel_delayed_work_sync(&par->local_work); | 819 | cancel_delayed_work_sync(&par->local_work); |
833 | unregister_framebuffer(info); | 820 | unregister_framebuffer(info); |
834 | 821 | ||
822 | mutex_lock(&par->bo_mutex); | ||
835 | (void) vmw_fb_kms_detach(par, true, true); | 823 | (void) vmw_fb_kms_detach(par, true, true); |
824 | mutex_unlock(&par->bo_mutex); | ||
836 | 825 | ||
837 | vfree(par->vmalloc); | 826 | vfree(par->vmalloc); |
838 | framebuffer_release(info); | 827 | framebuffer_release(info); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index f11601b6fd74..aacc9307ab0b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -2680,7 +2680,9 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, | |||
2680 | struct vmw_display_unit *du; | 2680 | struct vmw_display_unit *du; |
2681 | struct drm_display_mode *mode; | 2681 | struct drm_display_mode *mode; |
2682 | int i = 0; | 2682 | int i = 0; |
2683 | int ret = 0; | ||
2683 | 2684 | ||
2685 | mutex_lock(&dev_priv->dev->mode_config.mutex); | ||
2684 | list_for_each_entry(con, &dev_priv->dev->mode_config.connector_list, | 2686 | list_for_each_entry(con, &dev_priv->dev->mode_config.connector_list, |
2685 | head) { | 2687 | head) { |
2686 | if (i == unit) | 2688 | if (i == unit) |
@@ -2691,7 +2693,8 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, | |||
2691 | 2693 | ||
2692 | if (i != unit) { | 2694 | if (i != unit) { |
2693 | DRM_ERROR("Could not find initial display unit.\n"); | 2695 | DRM_ERROR("Could not find initial display unit.\n"); |
2694 | return -EINVAL; | 2696 | ret = -EINVAL; |
2697 | goto out_unlock; | ||
2695 | } | 2698 | } |
2696 | 2699 | ||
2697 | if (list_empty(&con->modes)) | 2700 | if (list_empty(&con->modes)) |
@@ -2699,7 +2702,8 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, | |||
2699 | 2702 | ||
2700 | if (list_empty(&con->modes)) { | 2703 | if (list_empty(&con->modes)) { |
2701 | DRM_ERROR("Could not find initial display mode.\n"); | 2704 | DRM_ERROR("Could not find initial display mode.\n"); |
2702 | return -EINVAL; | 2705 | ret = -EINVAL; |
2706 | goto out_unlock; | ||
2703 | } | 2707 | } |
2704 | 2708 | ||
2705 | du = vmw_connector_to_du(con); | 2709 | du = vmw_connector_to_du(con); |
@@ -2720,7 +2724,10 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, | |||
2720 | head); | 2724 | head); |
2721 | } | 2725 | } |
2722 | 2726 | ||
2723 | return 0; | 2727 | out_unlock: |
2728 | mutex_unlock(&dev_priv->dev->mode_config.mutex); | ||
2729 | |||
2730 | return ret; | ||
2724 | } | 2731 | } |
2725 | 2732 | ||
2726 | /** | 2733 | /** |