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