aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc.c
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2013-11-19 12:10:12 -0500
committerDave Airlie <airlied@redhat.com>2014-06-04 19:54:33 -0400
commit51fd371bbaf94018a1223b4e2cf20b9880fd92d4 (patch)
treee86e8ec3ace2fd61111105d39f5eb2d37378e9a8 /drivers/gpu/drm/drm_crtc.c
parent4f71d0cb76339a10fd445b0b281acc45c71b6271 (diff)
drm: convert crtc and connection_mutex to ww_mutex (v5)
For atomic, it will be quite necessary to not need to care so much about locking order. And 'state' gives us a convenient place to stash a ww_ctx for any sort of update that needs to grab multiple crtc locks. Because we will want to eventually make locking even more fine grained (giving locks to planes, connectors, etc), split out drm_modeset_lock and drm_modeset_acquire_ctx to track acquired locks. Atomic will use this to keep track of which locks have been acquired in a transaction. v1: original v2: remove a few things not needed until atomic, for now v3: update for v3 of connection_mutex patch.. v4: squash in docbook v5: doc tweaks/fixes Signed-off-by: Rob Clark <robdclark@gmail.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc.c')
-rw-r--r--drivers/gpu/drm/drm_crtc.c85
1 files changed, 63 insertions, 22 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index f3b98d4b6f46..43735f38cd17 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -37,6 +37,7 @@
37#include <drm/drm_crtc.h> 37#include <drm/drm_crtc.h>
38#include <drm/drm_edid.h> 38#include <drm/drm_edid.h>
39#include <drm/drm_fourcc.h> 39#include <drm/drm_fourcc.h>
40#include <drm/drm_modeset_lock.h>
40 41
41#include "drm_crtc_internal.h" 42#include "drm_crtc_internal.h"
42 43
@@ -50,14 +51,42 @@
50 */ 51 */
51void drm_modeset_lock_all(struct drm_device *dev) 52void drm_modeset_lock_all(struct drm_device *dev)
52{ 53{
53 struct drm_crtc *crtc; 54 struct drm_mode_config *config = &dev->mode_config;
55 struct drm_modeset_acquire_ctx *ctx;
56 int ret;
54 57
55 mutex_lock(&dev->mode_config.mutex); 58 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
59 if (WARN_ON(!ctx))
60 return;
56 61
57 mutex_lock(&dev->mode_config.connection_mutex); 62 mutex_lock(&config->mutex);
58 63
59 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 64 drm_modeset_acquire_init(ctx, 0);
60 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); 65
66retry:
67 ret = drm_modeset_lock(&config->connection_mutex, ctx);
68 if (ret)
69 goto fail;
70 ret = drm_modeset_lock_all_crtcs(dev, ctx);
71 if (ret)
72 goto fail;
73
74 WARN_ON(config->acquire_ctx);
75
76 /* now we hold the locks, so now that it is safe, stash the
77 * ctx for drm_modeset_unlock_all():
78 */
79 config->acquire_ctx = ctx;
80
81 drm_warn_on_modeset_not_all_locked(dev);
82
83 return;
84
85fail:
86 if (ret == -EDEADLK) {
87 drm_modeset_backoff(ctx);
88 goto retry;
89 }
61} 90}
62EXPORT_SYMBOL(drm_modeset_lock_all); 91EXPORT_SYMBOL(drm_modeset_lock_all);
63 92
@@ -69,12 +98,17 @@ EXPORT_SYMBOL(drm_modeset_lock_all);
69 */ 98 */
70void drm_modeset_unlock_all(struct drm_device *dev) 99void drm_modeset_unlock_all(struct drm_device *dev)
71{ 100{
72 struct drm_crtc *crtc; 101 struct drm_mode_config *config = &dev->mode_config;
102 struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
73 103
74 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 104 if (WARN_ON(!ctx))
75 mutex_unlock(&crtc->mutex); 105 return;
106
107 config->acquire_ctx = NULL;
108 drm_modeset_drop_locks(ctx);
109 drm_modeset_acquire_fini(ctx);
76 110
77 mutex_unlock(&dev->mode_config.connection_mutex); 111 kfree(ctx);
78 112
79 mutex_unlock(&dev->mode_config.mutex); 113 mutex_unlock(&dev->mode_config.mutex);
80} 114}
@@ -95,9 +129,9 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
95 return; 129 return;
96 130
97 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 131 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
98 WARN_ON(!mutex_is_locked(&crtc->mutex)); 132 WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
99 133
100 WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex)); 134 WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
101 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); 135 WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
102} 136}
103EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); 137EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
@@ -671,6 +705,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
671} 705}
672EXPORT_SYMBOL(drm_framebuffer_remove); 706EXPORT_SYMBOL(drm_framebuffer_remove);
673 707
708DEFINE_WW_CLASS(crtc_ww_class);
709
674/** 710/**
675 * drm_crtc_init_with_planes - Initialise a new CRTC object with 711 * drm_crtc_init_with_planes - Initialise a new CRTC object with
676 * specified primary and cursor planes. 712 * specified primary and cursor planes.
@@ -690,6 +726,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
690 void *cursor, 726 void *cursor,
691 const struct drm_crtc_funcs *funcs) 727 const struct drm_crtc_funcs *funcs)
692{ 728{
729 struct drm_mode_config *config = &dev->mode_config;
693 int ret; 730 int ret;
694 731
695 crtc->dev = dev; 732 crtc->dev = dev;
@@ -697,8 +734,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
697 crtc->invert_dimensions = false; 734 crtc->invert_dimensions = false;
698 735
699 drm_modeset_lock_all(dev); 736 drm_modeset_lock_all(dev);
700 mutex_init(&crtc->mutex); 737 drm_modeset_lock_init(&crtc->mutex);
701 mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex); 738 /* dropped by _unlock_all(): */
739 drm_modeset_lock(&crtc->mutex, config->acquire_ctx);
702 740
703 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC); 741 ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
704 if (ret) 742 if (ret)
@@ -706,8 +744,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
706 744
707 crtc->base.properties = &crtc->properties; 745 crtc->base.properties = &crtc->properties;
708 746
709 list_add_tail(&crtc->head, &dev->mode_config.crtc_list); 747 list_add_tail(&crtc->head, &config->crtc_list);
710 dev->mode_config.num_crtc++; 748 config->num_crtc++;
711 749
712 crtc->primary = primary; 750 crtc->primary = primary;
713 if (primary) 751 if (primary)
@@ -735,6 +773,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
735 kfree(crtc->gamma_store); 773 kfree(crtc->gamma_store);
736 crtc->gamma_store = NULL; 774 crtc->gamma_store = NULL;
737 775
776 drm_modeset_lock_fini(&crtc->mutex);
777
738 drm_mode_object_put(dev, &crtc->base); 778 drm_mode_object_put(dev, &crtc->base);
739 list_del(&crtc->head); 779 list_del(&crtc->head);
740 dev->mode_config.num_crtc--; 780 dev->mode_config.num_crtc--;
@@ -1798,7 +1838,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
1798 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id); 1838 DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
1799 1839
1800 mutex_lock(&dev->mode_config.mutex); 1840 mutex_lock(&dev->mode_config.mutex);
1801 mutex_lock(&dev->mode_config.connection_mutex); 1841 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1802 1842
1803 connector = drm_connector_find(dev, out_resp->connector_id); 1843 connector = drm_connector_find(dev, out_resp->connector_id);
1804 if (!connector) { 1844 if (!connector) {
@@ -1897,7 +1937,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
1897 out_resp->count_encoders = encoders_count; 1937 out_resp->count_encoders = encoders_count;
1898 1938
1899out: 1939out:
1900 mutex_unlock(&dev->mode_config.connection_mutex); 1940 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1901 mutex_unlock(&dev->mode_config.mutex); 1941 mutex_unlock(&dev->mode_config.mutex);
1902 1942
1903 return ret; 1943 return ret;
@@ -2481,7 +2521,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2481 return -ENOENT; 2521 return -ENOENT;
2482 } 2522 }
2483 2523
2484 mutex_lock(&crtc->mutex); 2524 drm_modeset_lock(&crtc->mutex, NULL);
2485 if (req->flags & DRM_MODE_CURSOR_BO) { 2525 if (req->flags & DRM_MODE_CURSOR_BO) {
2486 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) { 2526 if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
2487 ret = -ENXIO; 2527 ret = -ENXIO;
@@ -2505,7 +2545,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
2505 } 2545 }
2506 } 2546 }
2507out: 2547out:
2508 mutex_unlock(&crtc->mutex); 2548 drm_modeset_unlock(&crtc->mutex);
2509 2549
2510 return ret; 2550 return ret;
2511 2551
@@ -4198,7 +4238,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
4198 if (!crtc) 4238 if (!crtc)
4199 return -ENOENT; 4239 return -ENOENT;
4200 4240
4201 mutex_lock(&crtc->mutex); 4241 drm_modeset_lock(&crtc->mutex, NULL);
4202 if (crtc->primary->fb == NULL) { 4242 if (crtc->primary->fb == NULL) {
4203 /* The framebuffer is currently unbound, presumably 4243 /* The framebuffer is currently unbound, presumably
4204 * due to a hotplug event, that userspace has not 4244 * due to a hotplug event, that userspace has not
@@ -4282,7 +4322,7 @@ out:
4282 drm_framebuffer_unreference(fb); 4322 drm_framebuffer_unreference(fb);
4283 if (old_fb) 4323 if (old_fb)
4284 drm_framebuffer_unreference(old_fb); 4324 drm_framebuffer_unreference(old_fb);
4285 mutex_unlock(&crtc->mutex); 4325 drm_modeset_unlock(&crtc->mutex);
4286 4326
4287 return ret; 4327 return ret;
4288} 4328}
@@ -4647,7 +4687,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
4647void drm_mode_config_init(struct drm_device *dev) 4687void drm_mode_config_init(struct drm_device *dev)
4648{ 4688{
4649 mutex_init(&dev->mode_config.mutex); 4689 mutex_init(&dev->mode_config.mutex);
4650 mutex_init(&dev->mode_config.connection_mutex); 4690 drm_modeset_lock_init(&dev->mode_config.connection_mutex);
4651 mutex_init(&dev->mode_config.idr_mutex); 4691 mutex_init(&dev->mode_config.idr_mutex);
4652 mutex_init(&dev->mode_config.fb_lock); 4692 mutex_init(&dev->mode_config.fb_lock);
4653 INIT_LIST_HEAD(&dev->mode_config.fb_list); 4693 INIT_LIST_HEAD(&dev->mode_config.fb_list);
@@ -4747,5 +4787,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
4747 } 4787 }
4748 4788
4749 idr_destroy(&dev->mode_config.crtc_idr); 4789 idr_destroy(&dev->mode_config.crtc_idr);
4790 drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
4750} 4791}
4751EXPORT_SYMBOL(drm_mode_config_cleanup); 4792EXPORT_SYMBOL(drm_mode_config_cleanup);