diff options
| author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-11-28 16:10:05 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2011-12-02 05:47:15 -0500 |
| commit | 6eebd6bb5f1ea04f04019e5c39f87a0f17ffb472 (patch) | |
| tree | 798912a7e21dded899b612a6828d0b104c27c25f | |
| parent | 2ed4d9d648cbd4fb1c232a646dbdbdfdd373ca94 (diff) | |
drm: Fix lack of CRTC disable for drm_crtc_helper_set_config(.fb=NULL)
Disabling the CRTC by setting its framebuffer to NULL, as used by
drm_framebuffer_cleanup(), was failing to pass the current framebuffer
to the crtc_func->disable callback. This is because of the dance within
drm_crtc_helper_set_config to pass the new_fb (NULL in this case) to the
drm_crtc_helper_set_mode with the currently attached fb as a parameter.
drm_crtc_helper_set_mode treats this as a no-op and the encoder is still
enabled. And so the current fb is forgotten before the call to
drm_helper_disable_unused_functions.
This patch treats disabling the CRTC as a simple special case rather
than adding further complexity into the configuration logic.
This fixes a pin-leak of the fb bo on Xserver close.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 3969f7553fe7..d2619d72cece 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -456,6 +456,30 @@ done: | |||
| 456 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); | 456 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
| 457 | 457 | ||
| 458 | 458 | ||
| 459 | static int | ||
| 460 | drm_crtc_helper_disable(struct drm_crtc *crtc) | ||
| 461 | { | ||
| 462 | struct drm_device *dev = crtc->dev; | ||
| 463 | struct drm_connector *connector; | ||
| 464 | struct drm_encoder *encoder; | ||
| 465 | |||
| 466 | /* Decouple all encoders and their attached connectors from this crtc */ | ||
| 467 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 468 | if (encoder->crtc != crtc) | ||
| 469 | continue; | ||
| 470 | |||
| 471 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 472 | if (connector->encoder != encoder) | ||
| 473 | continue; | ||
| 474 | |||
| 475 | connector->encoder = NULL; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | drm_helper_disable_unused_functions(dev); | ||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 459 | /** | 483 | /** |
| 460 | * drm_crtc_helper_set_config - set a new config from userspace | 484 | * drm_crtc_helper_set_config - set a new config from userspace |
| 461 | * @crtc: CRTC to setup | 485 | * @crtc: CRTC to setup |
| @@ -510,8 +534,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) | |||
| 510 | (int)set->num_connectors, set->x, set->y); | 534 | (int)set->num_connectors, set->x, set->y); |
| 511 | } else { | 535 | } else { |
| 512 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); | 536 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
| 513 | set->mode = NULL; | 537 | return drm_crtc_helper_disable(set->crtc); |
| 514 | set->num_connectors = 0; | ||
| 515 | } | 538 | } |
| 516 | 539 | ||
| 517 | dev = set->crtc->dev; | 540 | dev = set->crtc->dev; |
