Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ef5f72f authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@redhat.com>
parent 6a719e05
Loading
Loading
Loading
Loading
+12 −28
Original line number Diff line number Diff line
@@ -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);

/**
 * 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
 * @dev: DRM device
@@ -328,11 +303,20 @@ void drm_framebuffer_cleanup(struct drm_framebuffer *fb)
{
	struct drm_device *dev = fb->dev;
	struct drm_crtc *crtc;
	struct drm_mode_set set;
	int ret;

	/* remove from any CRTC */
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		if (crtc->fb == fb)
			crtc->fb = NULL;
		if (crtc->fb == fb) {
			/* 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);