aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2012-03-13 06:35:46 -0400
committerDave Airlie <airlied@redhat.com>2012-03-15 05:51:42 -0400
commitac235dafb60d3ba4fa4e7341503b16d6e0645ee7 (patch)
treea544dc5b4c4677b9627d82f87845d93be4fcb0c2
parent5f61bb421f01023986902200b6486978c07176f7 (diff)
drm: Fix drm_mode_attachmode_crtc()
Change drm_mode_attachmode_crtc() to take an "all or nothing" approach. If an error is returned, there are no side effects visible. Also change the function to always duplicate the mode passed in. Also change the function to not give up when it finds the first connector without and encoder. A simpler approach would be to just remove the function completely as it's unused currently. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_crtc.c38
-rw-r--r--include/drm/drm_crtc.h2
2 files changed, 28 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3f5c603f9a2c..37d34ad3a0b8 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2421,24 +2421,40 @@ static void drm_mode_attachmode(struct drm_device *dev,
2421} 2421}
2422 2422
2423int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc, 2423int drm_mode_attachmode_crtc(struct drm_device *dev, struct drm_crtc *crtc,
2424 struct drm_display_mode *mode) 2424 const struct drm_display_mode *mode)
2425{ 2425{
2426 struct drm_connector *connector; 2426 struct drm_connector *connector;
2427 struct drm_display_mode *dup_mode; 2427 int ret = 0;
2428 int need_dup = 0; 2428 struct drm_display_mode *dup_mode, *next;
2429 LIST_HEAD(list);
2430
2429 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 2431 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2430 if (!connector->encoder) 2432 if (!connector->encoder)
2431 break; 2433 continue;
2432 if (connector->encoder->crtc == crtc) { 2434 if (connector->encoder->crtc == crtc) {
2433 if (need_dup) 2435 dup_mode = drm_mode_duplicate(dev, mode);
2434 dup_mode = drm_mode_duplicate(dev, mode); 2436 if (!dup_mode) {
2435 else 2437 ret = -ENOMEM;
2436 dup_mode = mode; 2438 goto out;
2437 drm_mode_attachmode(dev, connector, dup_mode); 2439 }
2438 need_dup = 1; 2440 list_add_tail(&dup_mode->head, &list);
2439 } 2441 }
2440 } 2442 }
2441 return 0; 2443
2444 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
2445 if (!connector->encoder)
2446 continue;
2447 if (connector->encoder->crtc == crtc)
2448 list_move_tail(list.next, &connector->user_modes);
2449 }
2450
2451 WARN_ON(!list_empty(&list));
2452
2453 out:
2454 list_for_each_entry_safe(dup_mode, next, &list, head)
2455 drm_mode_destroy(dev, dup_mode);
2456
2457 return ret;
2442} 2458}
2443EXPORT_SYMBOL(drm_mode_attachmode_crtc); 2459EXPORT_SYMBOL(drm_mode_attachmode_crtc);
2444 2460
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 31715bd4f42a..fe7ebc6b8c93 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -869,7 +869,7 @@ extern int drm_mode_height(struct drm_display_mode *mode);
869/* for us by fb module */ 869/* for us by fb module */
870extern int drm_mode_attachmode_crtc(struct drm_device *dev, 870extern int drm_mode_attachmode_crtc(struct drm_device *dev,
871 struct drm_crtc *crtc, 871 struct drm_crtc *crtc,
872 struct drm_display_mode *mode); 872 const struct drm_display_mode *mode);
873extern int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode); 873extern int drm_mode_detachmode_crtc(struct drm_device *dev, struct drm_display_mode *mode);
874 874
875extern struct drm_display_mode *drm_mode_create(struct drm_device *dev); 875extern struct drm_display_mode *drm_mode_create(struct drm_device *dev);