[Openchrome-devel] drm-openchrome: drivers/gpu/drm

James Simmons jsimmons at kemper.freedesktop.org
Sun Dec 23 06:38:06 PST 2012


 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 <jsimmons at 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;
 }


More information about the Openchrome-devel mailing list