drivers/gpu/drm/via/via_display.c |    5 -
 drivers/gpu/drm/via/via_display.h |    2 
 drivers/gpu/drm/via/via_drv.c     |   15 ++++-
 drivers/gpu/drm/via/via_drv.h     |    1 
 drivers/gpu/drm/via/via_fb.c      |   96 ++++++++++++++++++++++++++------------
 5 files changed, 82 insertions(+), 37 deletions(-)

New commits:
commit 9294feac3dc0616737df7073749041382d01e2af
Author: James Simmons <jsimm...@infradead.org>
Date:   Sun Dec 23 09:37:52 2012 -0500

    Fixed various memory leaks for fbdev emulation layer. Use MTRR if avaliable.

diff --git a/drivers/gpu/drm/via/via_display.c 
b/drivers/gpu/drm/via/via_display.c
index 3bf99a9..29cdec1 100644
--- a/drivers/gpu/drm/via/via_display.c
+++ b/drivers/gpu/drm/via/via_display.c
@@ -491,10 +491,7 @@ via_modeset_init(struct drm_device *dev)
 
 void via_modeset_fini(struct drm_device *dev)
 {
-       struct drm_via_private *dev_priv = dev->dev_private;
-
-       via_framebuffer_fini(dev_priv->helper);
-
+       via_framebuffer_fini(dev);
        drm_mode_config_cleanup(dev);
 
        via_i2c_exit();
diff --git a/drivers/gpu/drm/via/via_display.h 
b/drivers/gpu/drm/via/via_display.h
index f233ad2..6a54548 100644
--- a/drivers/gpu/drm/via/via_display.h
+++ b/drivers/gpu/drm/via/via_display.h
@@ -133,7 +133,7 @@ extern void via_set_vclock(struct drm_crtc *crtc, u32 clk);
 
 /* framebuffers */
 extern int via_framebuffer_init(struct drm_device *dev, struct drm_fb_helper 
**ptr);
-extern void via_framebuffer_fini(struct drm_fb_helper *helper);
+extern void via_framebuffer_fini(struct drm_device *dev);
 
 /* crtc */
 extern void via_crtc_init(struct drm_device *dev, int index);
diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c
index d39d50d..f4c3db1 100644
--- a/drivers/gpu/drm/via/via_drv.c
+++ b/drivers/gpu/drm/via/via_drv.c
@@ -274,10 +274,19 @@ static int via_driver_unload(struct drm_device *dev)
                ttm_bo_unref(&bo);
        }
 
-       ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_PRIV0);
-       ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
-       ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_TT);
+       /* mtrr delete the vram */
+       if (drm_core_has_MTRR(dev) && (dev_priv->vram_mtrr >= 0)) {
+               int size = dev_priv->bdev.man[TTM_PL_VRAM].size;
+               unsigned long long vram_start;
 
+               if (dev->pci_device == PCI_DEVICE_ID_VIA_VX900)
+                       vram_start = pci_resource_start(dev->pdev, 2);
+               else
+                       vram_start = pci_resource_start(dev->pdev, 0);
+               mtrr_del(dev_priv->vram_mtrr, vram_start, size);
+       }
+
+       ttm_bo_device_release(&dev_priv->bdev);
        ttm_global_fini(&dev_priv->mem_global_ref,
                        &dev_priv->bo_global_ref,
                        &dev_priv->bdev);
diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h
index 2faa473..06a5af5 100644
--- a/drivers/gpu/drm/via/via_drv.h
+++ b/drivers/gpu/drm/via/via_drv.h
@@ -104,6 +104,7 @@ struct drm_via_private {
        struct ttm_bo_kmap_obj vq;
 
        struct drm_fb_helper *helper;
+       int vram_mtrr;
        u8 vram_type;
 
        struct via_state pm_cache;
diff --git a/drivers/gpu/drm/via/via_fb.c b/drivers/gpu/drm/via/via_fb.c
index 7e75d53..2941b16 100644
--- a/drivers/gpu/drm/via/via_fb.c
+++ b/drivers/gpu/drm/via/via_fb.c
@@ -22,8 +22,6 @@
  */
 #include "drmP.h"
 #include "via_drv.h"
-
-#include "drm_pciids.h"
 #include "drm_fb_helper.h"
 #include "drm_crtc_helper.h"
 
@@ -898,6 +896,11 @@ int via_detect_vram(struct drm_device *dev)
                break;
        }
 
+       /* Add an MTRR for the VRAM */
+       if (drm_core_has_MTRR(dev))
+               dev_priv->vram_mtrr = mtrr_add(vram_start, vram_size,
+                                               MTRR_TYPE_WRCOMB, 1);
+
        ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM, vram_size >> 
PAGE_SHIFT);
        if (!ret) {
                DRM_INFO("Detected %llu MB of %s Video RAM at physical address 
0x%08llx.\n",
@@ -931,6 +934,7 @@ via_user_framebuffer_destroy(struct drm_framebuffer *fb)
                fb->helper_private = NULL;
        }
        drm_framebuffer_cleanup(fb);
+       kfree(fb);
 }
 
 static const struct drm_framebuffer_funcs via_fb_funcs = {
@@ -941,6 +945,9 @@ static const struct drm_framebuffer_funcs via_fb_funcs = {
 static void
 via_output_poll_changed(struct drm_device *dev)
 {
+       struct drm_via_private *dev_priv = dev->dev_private;
+
+       drm_fb_helper_hotplug_event(dev_priv->helper);
 }
 
 static struct drm_framebuffer *
@@ -954,7 +961,8 @@ via_user_framebuffer_create(struct drm_device *dev,
 
        obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]);
        if (obj ==  NULL) {
-               DRM_ERROR("No GEM object available to create framebuffer\n");
+               DRM_ERROR("No GEM object found for handle 0x%08X\n",
+                               mode_cmd->handles[0]);
                return ERR_PTR(-ENOENT);
        }
 
@@ -1009,7 +1017,7 @@ via_fb_probe(struct drm_fb_helper *helper,
                                                        sizes->surface_depth);
        mode_cmd.pitches[0] = (mode_cmd.width * sizes->surface_bpp >> 3);
        mode_cmd.pitches[0] = round_up(mode_cmd.pitches[0], 16);
-       size= mode_cmd.pitches[0] * mode_cmd.height;
+       size = mode_cmd.pitches[0] * mode_cmd.height;
        size = ALIGN(size, PAGE_SIZE);
 
        obj = drm_gem_object_alloc(helper->dev, size);
@@ -1020,15 +1028,15 @@ via_fb_probe(struct drm_fb_helper *helper,
        ret = ttm_bo_allocate(&dev_priv->bdev, size, ttm_bo_type_kernel,
                                TTM_PL_FLAG_VRAM, 1, PAGE_SIZE, false,
                                NULL, obj->filp, &kmap->bo);
-       if (ret)
+       if (unlikely(ret))
                goto out_err;
 
        ret = ttm_bo_pin(kmap->bo, kmap);
-       if (ret)
+       if (unlikely(ret))
                goto out_err;
 
        ret = drm_framebuffer_init(helper->dev, fb, &via_fb_funcs);
-       if (ret)
+       if (unlikely(ret))
                goto out_err;
 
        obj->driver_private = kmap->bo;
@@ -1040,13 +1048,15 @@ via_fb_probe(struct drm_fb_helper *helper,
 
        info->fix.smem_start = kmap->bo->mem.bus.base +
                                kmap->bo->mem.bus.offset;
-       info->fix.smem_len = kmap->bo->num_pages << PAGE_SHIFT;
-       info->screen_size = kmap->bo->num_pages << PAGE_SHIFT;
+       info->fix.smem_len = info->screen_size = size;
        info->screen_base = kmap->virtual;
 
+       /* setup aperture base/size for takeover (vesafb, efifb etc) */
        ap = alloc_apertures(1);
-       if (!ap)
+       if (!ap) {
+               drm_framebuffer_cleanup(fb);
                goto out_err;
+       }
        ap->ranges[0].size = kmap->bo->bdev->man[kmap->bo->mem.mem_type].size;
        ap->ranges[0].base = kmap->bo->mem.bus.base;
        info->apertures = ap;
@@ -1066,9 +1076,7 @@ out_err:
                        drm_gem_object_unreference_unlocked(obj);
                        helper->fb->helper_private = NULL;
                }
-
-               if (ptr)
-                       kfree(ptr);
+               kfree(ptr);
        }
        return ret;
 }
@@ -1078,12 +1086,32 @@ static void
 via_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
                u16 blue, int regno)
 {
+       int size = crtc->gamma_size * sizeof(uint16_t);
+       u16 *r_base, *g_base, *b_base;
+
+       r_base = crtc->gamma_store;
+       g_base = r_base + size;
+       b_base = g_base + size;
+
+       r_base[regno] = red;
+       g_base[regno] = green;
+       b_base[regno] = blue;
 }
 
 static void
 via_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
                u16 *blue, int regno)
 {
+       int size = crtc->gamma_size * sizeof(uint16_t);
+       u16 *r_base, *g_base, *b_base;
+
+       r_base = crtc->gamma_store;
+       g_base = r_base + size;
+       b_base = g_base + size;
+
+       *red = r_base[regno];
+       *green = g_base[regno];
+       *blue = b_base[regno];
 }
 
 static struct drm_fb_helper_funcs via_fb_helper_funcs = {
@@ -1092,7 +1120,8 @@ static struct drm_fb_helper_funcs via_fb_helper_funcs = {
        .fb_probe = via_fb_probe,
 };
 
-int drmfb_helper_pan_display(struct fb_var_screeninfo *var,
+int
+drmfb_helper_pan_display(struct fb_var_screeninfo *var,
                                struct fb_info *info)
 {
        struct drm_fb_helper *fb_helper = info->par;
@@ -1130,20 +1159,21 @@ int drmfb_helper_pan_display(struct fb_var_screeninfo 
*var,
 }
 
 static struct fb_ops viafb_ops = {
-       .owner = THIS_MODULE,
-       .fb_check_var = drm_fb_helper_check_var,
-       .fb_set_par = drm_fb_helper_set_par,
-       .fb_fillrect = cfb_fillrect,
-       .fb_copyarea = cfb_copyarea,
-       .fb_imageblit = cfb_imageblit,
-       .fb_pan_display = drmfb_helper_pan_display,
-       .fb_blank = drm_fb_helper_blank,
-       .fb_setcmap = drm_fb_helper_setcmap,
-       .fb_debug_enter = drm_fb_helper_debug_enter,
-       .fb_debug_leave = drm_fb_helper_debug_leave,
+       .owner          = THIS_MODULE,
+       .fb_check_var   = drm_fb_helper_check_var,
+       .fb_set_par     = drm_fb_helper_set_par,
+       .fb_fillrect    = cfb_fillrect,
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_pan_display = drmfb_helper_pan_display,
+       .fb_blank       = drm_fb_helper_blank,
+       .fb_setcmap     = drm_fb_helper_setcmap,
+       .fb_debug_enter = drm_fb_helper_debug_enter,
+       .fb_debug_leave = drm_fb_helper_debug_leave,
 };
 
-int via_framebuffer_init(struct drm_device *dev, struct drm_fb_helper **ptr)
+int
+via_framebuffer_init(struct drm_device *dev, struct drm_fb_helper **ptr)
 {
        struct drm_fb_helper *helper;
        struct fb_info *info;
@@ -1152,8 +1182,10 @@ int via_framebuffer_init(struct drm_device *dev, struct 
drm_fb_helper **ptr)
        dev->mode_config.funcs = (void *)&via_mode_funcs;
 
        info = framebuffer_alloc(sizeof(*helper), dev->dev);
-       if (!info)
+       if (!info) {
+               DRM_ERROR("allocate fb_info error\n");
                return ret;
+       }
 
        helper = info->par;
        helper->fbdev = info;
@@ -1187,12 +1219,15 @@ int via_framebuffer_init(struct drm_device *dev, struct 
drm_fb_helper **ptr)
        *ptr = helper;
 out_err:
        if (ret)
-               kfree(info);
+               framebuffer_release(info);
        return ret;
 }
 
-void via_framebuffer_fini(struct drm_fb_helper *helper)
+void
+via_framebuffer_fini(struct drm_device *dev)
 {
+       struct drm_via_private *dev_priv = dev->dev_private;
+       struct drm_fb_helper *helper = dev_priv->helper;
        struct ttm_bo_kmap_obj *kmap = helper->helper_private;
        struct fb_info *info = helper->fbdev;
        struct drm_gem_object *obj;
@@ -1221,4 +1256,7 @@ void via_framebuffer_fini(struct drm_fb_helper *helper)
        }
        drm_fb_helper_fini(helper);
        drm_framebuffer_cleanup(helper->fb);
+
+       kfree(dev_priv->helper);
+       dev_priv->helper = NULL;
 }
_______________________________________________
Openchrome-devel mailing list
Openchrome-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/openchrome-devel

Reply via email to