]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: drm/exynos: make exynos_drm_fb_release callable from atomic context
authorMandeep Singh Baines <msb@chromium.org>
Wed, 28 Nov 2012 21:04:28 +0000 (13:04 -0800)
committerGerrit <chrome-bot@google.com>
Fri, 30 Nov 2012 22:42:45 +0000 (14:42 -0800)
We want to be able to call fb_put from the finish_pageflip. To fix
the IOMMU page fault issue we need to grab/release a ref for every
page flip.

BUG=chrome-os-partner:15349,chrome-os-partner:14965
TEST=Verify that we aren't leaking (see below).

localhost ~ # cat /sys/kernel/debug/dri/0/exynos_gem_objects
5 objects, 12709888 bytes
localhost ~ # restart ui
ui start/running, process 3529
localhost ~ # cat /sys/kernel/debug/dri/0/exynos_gem_objects
5 objects, 12709888 bytes

Signed-off-by: Mandeep Singh Baines <msb@chromium.org>
Change-Id: I48507f23345e232ef8492e0d86aef9c25ae5a41b
Reviewed-on: https://gerrit.chromium.org/gerrit/38896

drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_fb.c

index 9eb3387d32b5f5286d7e14cd33e6929fa84033cf..11ce63e2f6c72105398bb3ab0d80917d17d058f9 100644 (file)
@@ -227,11 +227,13 @@ int exynos_drm_encoder_get_dpms(struct drm_encoder *encoder);
 /*
  * exynos specific framebuffer structure.
  *
+ * @release_work: for the worker destroying the fb after it's done being used
  * @fb: drm framebuffer obejct.
  * @exynos_gem_obj: array of exynos specific gem object containing a gem object.
  */
 struct exynos_drm_fb {
        struct kref                     refcount;
+       struct work_struct              release_work;
        struct drm_framebuffer          fb;
        struct exynos_drm_gem_obj       *exynos_gem_obj[MAX_FB_BUFFER];
 #ifdef CONFIG_DMA_SHARED_BUFFER_USES_KDS
index efa6f09aae59000c8f83a15bc03ae482d63f18cc..ebc8412a4893bea397e289068b8057c945ee4db0 100644 (file)
@@ -150,6 +150,14 @@ void exynos_drm_kds_callback_rm_fb(void *callback_parameter,
 #endif
 
 void exynos_drm_fb_release(struct kref *kref)
+{
+       struct exynos_drm_fb *exynos_fb;
+
+       exynos_fb = container_of(kref, struct exynos_drm_fb, refcount);
+       schedule_work(&exynos_fb->release_work);
+}
+
+static void exynos_drm_fb_release_work_fn(struct work_struct *work)
 {
        struct drm_framebuffer *fb;
        struct exynos_drm_fb *exynos_fb;
@@ -158,7 +166,7 @@ void exynos_drm_fb_release(struct kref *kref)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       exynos_fb = container_of(kref, struct exynos_drm_fb, refcount);
+       exynos_fb = container_of(work, struct exynos_drm_fb, release_work);
        fb = &exynos_fb->fb;
        dev_priv = fb->dev->dev_private;
 
@@ -252,6 +260,7 @@ exynos_drm_framebuffer_init(struct drm_device *dev,
        }
 
        kref_init(&exynos_fb->refcount);
+       INIT_WORK(&exynos_fb->release_work, exynos_drm_fb_release_work_fn);
 
        ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs);
        if (ret) {