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>
This commit is contained in:
@@ -257,31 +257,6 @@ void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_mode_object_find);
|
EXPORT_SYMBOL(drm_mode_object_find);
|
||||||
|
|
||||||
/**
|
|
||||||
* drm_crtc_from_fb - find the CRTC structure associated with an fb
|
|
||||||
* @dev: DRM device
|
|
||||||
* @fb: framebuffer in question
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
* Caller must hold mode_config lock.
|
|
||||||
*
|
|
||||||
* Find CRTC in the mode_config structure that matches @fb.
|
|
||||||
*
|
|
||||||
* RETURNS:
|
|
||||||
* Pointer to the CRTC or NULL if it wasn't found.
|
|
||||||
*/
|
|
||||||
struct drm_crtc *drm_crtc_from_fb(struct drm_device *dev,
|
|
||||||
struct drm_framebuffer *fb)
|
|
||||||
{
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
|
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
|
||||||
if (crtc->fb == fb)
|
|
||||||
return crtc;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_framebuffer_init - initialize a framebuffer
|
* drm_framebuffer_init - initialize a framebuffer
|
||||||
* @dev: DRM device
|
* @dev: DRM device
|
||||||
@@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
|
|||||||
{
|
{
|
||||||
struct drm_device *dev = fb->dev;
|
struct drm_device *dev = fb->dev;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
|
struct drm_mode_set set;
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* remove from any CRTC */
|
/* remove from any CRTC */
|
||||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||||
if (crtc->fb == fb)
|
if (crtc->fb == fb) {
|
||||||
crtc->fb = NULL;
|
/* should turn off the crtc */
|
||||||
|
memset(&set, 0, sizeof(struct drm_mode_set));
|
||||||
|
set.crtc = crtc;
|
||||||
|
set.fb = NULL;
|
||||||
|
ret = crtc->funcs->set_config(&set);
|
||||||
|
if (ret)
|
||||||
|
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drm_mode_object_put(dev, &fb->base);
|
drm_mode_object_put(dev, &fb->base);
|
||||||
|
Reference in New Issue
Block a user