diff options
author | Dave Airlie <airlied@redhat.com> | 2009-08-16 23:11:23 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-08-19 00:11:34 -0400 |
commit | 5ef5f72febfea420ce58f670bad83830a5e5e3de (patch) | |
tree | de55d4d968b50611c2fd64f50ce502f14b0fc8a8 /drivers/gpu | |
parent | 6a719e05330ef19acd9392dbbfb95a774776dee5 (diff) |
drm/kms: teardown crtc correctly when fb is destroyed.
If userspace destroys a framebuffer that is in use on a crtc,
don't just null it out, tear down the crtc properly so the
hw gets turned off.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 40 |
1 files changed, 12 insertions, 28 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 33be210d6723..2f631c75f704 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -258,31 +258,6 @@ void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type) | |||
258 | EXPORT_SYMBOL(drm_mode_object_find); | 258 | EXPORT_SYMBOL(drm_mode_object_find); |
259 | 259 | ||
260 | /** | 260 | /** |
261 | * drm_crtc_from_fb - find the CRTC structure associated with an fb | ||
262 | * @dev: DRM device | ||
263 | * @fb: framebuffer in question | ||
264 | * | ||
265 | * LOCKING: | ||
266 | * Caller must hold mode_config lock. | ||
267 | * | ||
268 | * Find CRTC in the mode_config structure that matches @fb. | ||
269 | * | ||
270 | * RETURNS: | ||
271 | * Pointer to the CRTC or NULL if it wasn't found. | ||
272 | */ | ||
273 | struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev, | ||
274 | struct drm_framebuffer *fb) | ||
275 | { | ||
276 | struct drm_crtc *crtc; | ||
277 | |||
278 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
279 | if (crtc->fb == fb) | ||
280 | return crtc; | ||
281 | } | ||
282 | return NULL; | ||
283 | } | ||
284 | |||
285 | /** | ||
286 | * drm_framebuffer_init - initialize a framebuffer | 261 | * drm_framebuffer_init - initialize a framebuffer |
287 | * @dev: DRM device | 262 | * @dev: DRM device |
288 | * | 263 | * |
@@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb) | |||
328 | { | 303 | { |
329 | struct drm_device *dev = fb->dev; | 304 | struct drm_device *dev = fb->dev; |
330 | struct drm_crtc *crtc; | 305 | struct drm_crtc *crtc; |
306 | struct drm_mode_set set; | ||
307 | int ret; | ||
331 | 308 | ||
332 | /* remove from any CRTC */ | 309 | /* remove from any CRTC */ |
333 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 310 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
334 | if (crtc->fb == fb) | 311 | if (crtc->fb == fb) { |
335 | crtc->fb = NULL; | 312 | /* should turn off the crtc */ |
313 | memset(&set, 0, sizeof(struct drm_mode_set)); | ||
314 | set.crtc = crtc; | ||
315 | set.fb = NULL; | ||
316 | ret = crtc->funcs->set_config(&set); | ||
317 | if (ret) | ||
318 | DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); | ||
319 | } | ||
336 | } | 320 | } |
337 | 321 | ||
338 | drm_mode_object_put(dev, &fb->base); | 322 | drm_mode_object_put(dev, &fb->base); |
@@ -1511,7 +1495,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, | |||
1511 | set.mode = mode; | 1495 | set.mode = mode; |
1512 | set.connectors = connector_set; | 1496 | set.connectors = connector_set; |
1513 | set.num_connectors = crtc_req->count_connectors; | 1497 | set.num_connectors = crtc_req->count_connectors; |
1514 | set.fb =fb; | 1498 | set.fb = fb; |
1515 | ret = crtc->funcs->set_config(&set); | 1499 | ret = crtc->funcs->set_config(&set); |
1516 | 1500 | ||
1517 | out: | 1501 | out: |