aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2009-08-16 23:11:23 -0400
committerDave Airlie <airlied@redhat.com>2009-08-19 00:11:34 -0400
commit5ef5f72febfea420ce58f670bad83830a5e5e3de (patch)
treede55d4d968b50611c2fd64f50ce502f14b0fc8a8
parent6a719e05330ef19acd9392dbbfb95a774776dee5 (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>
-rw-r--r--drivers/gpu/drm/drm_crtc.c40
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)
258EXPORT_SYMBOL(drm_mode_object_find); 258EXPORT_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 */
273struct 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
1517out: 1501out: