aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-02-10 12:00:39 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-02-12 12:53:02 -0500
commita8bb6818270c32126dba0fd2ddb139d885c5687d (patch)
tree56f0b21a168e442a3000cb517a93b84dba7ceacf
parentef2d633e9bcfdb73e536ca81b835dd015fe24ceb (diff)
drm/i915: Fix error path leak in fbdev fb allocation
In Jesse's patch to switch the fbdev framebuffer from an embedded struct to a pointer the kfree in case of an error was missed. Fix this up by using our own internal fb allocation helper directly instead of reinventing that wheel. We need a to_intel_framebuffer cast unfortunately since all the other callers of _create still look better whith using a drm_framebuffer as return pointer. v2: Add an unlocked __intel_framebuffer_create function since our dev->struct_mutex locking is too much a mess. With ppgtt we even need it to take a look at the global gtt offset of pinned objects, since the vma list might chance from underneath us. At least with the current global gtt lookup functions. Reported by Mika. Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c35
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c20
3 files changed, 36 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 6600931f213c..6ac4c23acc77 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7690,10 +7690,15 @@ static struct drm_display_mode load_detect_mode = {
7690 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC), 7690 704, 832, 0, 480, 489, 491, 520, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC),
7691}; 7691};
7692 7692
7693static struct drm_framebuffer * 7693static int intel_framebuffer_init(struct drm_device *dev,
7694intel_framebuffer_create(struct drm_device *dev, 7694 struct intel_framebuffer *ifb,
7695 struct drm_mode_fb_cmd2 *mode_cmd, 7695 struct drm_mode_fb_cmd2 *mode_cmd,
7696 struct drm_i915_gem_object *obj) 7696 struct drm_i915_gem_object *obj);
7697
7698struct drm_framebuffer *
7699__intel_framebuffer_create(struct drm_device *dev,
7700 struct drm_mode_fb_cmd2 *mode_cmd,
7701 struct drm_i915_gem_object *obj)
7697{ 7702{
7698 struct intel_framebuffer *intel_fb; 7703 struct intel_framebuffer *intel_fb;
7699 int ret; 7704 int ret;
@@ -7704,12 +7709,7 @@ intel_framebuffer_create(struct drm_device *dev,
7704 return ERR_PTR(-ENOMEM); 7709 return ERR_PTR(-ENOMEM);
7705 } 7710 }
7706 7711
7707 ret = i915_mutex_lock_interruptible(dev);
7708 if (ret)
7709 goto err;
7710
7711 ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); 7712 ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
7712 mutex_unlock(&dev->struct_mutex);
7713 if (ret) 7713 if (ret)
7714 goto err; 7714 goto err;
7715 7715
@@ -7721,6 +7721,23 @@ err:
7721 return ERR_PTR(ret); 7721 return ERR_PTR(ret);
7722} 7722}
7723 7723
7724struct drm_framebuffer *
7725intel_framebuffer_create(struct drm_device *dev,
7726 struct drm_mode_fb_cmd2 *mode_cmd,
7727 struct drm_i915_gem_object *obj)
7728{
7729 struct drm_framebuffer *fb;
7730 int ret;
7731
7732 ret = i915_mutex_lock_interruptible(dev);
7733 if (ret)
7734 return ERR_PTR(ret);
7735 fb = __intel_framebuffer_create(dev, mode_cmd, obj);
7736 mutex_unlock(&dev->struct_mutex);
7737
7738 return fb;
7739}
7740
7724static u32 7741static u32
7725intel_framebuffer_pitch_for_width(int width, int bpp) 7742intel_framebuffer_pitch_for_width(int width, int bpp)
7726{ 7743{
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 59348a4d0238..aff9171a91d8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -681,8 +681,8 @@ int intel_pin_and_fence_fb_obj(struct drm_device *dev,
681 struct drm_i915_gem_object *obj, 681 struct drm_i915_gem_object *obj,
682 struct intel_ring_buffer *pipelined); 682 struct intel_ring_buffer *pipelined);
683void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); 683void intel_unpin_fb_obj(struct drm_i915_gem_object *obj);
684int intel_framebuffer_init(struct drm_device *dev, 684struct drm_framebuffer *
685 struct intel_framebuffer *ifb, 685__intel_framebuffer_create(struct drm_device *dev,
686 struct drm_mode_fb_cmd2 *mode_cmd, 686 struct drm_mode_fb_cmd2 *mode_cmd,
687 struct drm_i915_gem_object *obj); 687 struct drm_i915_gem_object *obj);
688void intel_prepare_page_flip(struct drm_device *dev, int plane); 688void intel_prepare_page_flip(struct drm_device *dev, int plane);
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 9aa26e59a1ab..cf4627387c5a 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -62,20 +62,12 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
62{ 62{
63 struct intel_fbdev *ifbdev = 63 struct intel_fbdev *ifbdev =
64 container_of(helper, struct intel_fbdev, helper); 64 container_of(helper, struct intel_fbdev, helper);
65 struct intel_framebuffer *fb; 65 struct drm_framebuffer *fb;
66 struct drm_device *dev = helper->dev; 66 struct drm_device *dev = helper->dev;
67 struct drm_mode_fb_cmd2 mode_cmd = {}; 67 struct drm_mode_fb_cmd2 mode_cmd = {};
68 struct drm_i915_gem_object *obj; 68 struct drm_i915_gem_object *obj;
69 int size, ret; 69 int size, ret;
70 70
71 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
72 if (!fb) {
73 ret = -ENOMEM;
74 goto out;
75 }
76
77 ifbdev->fb = fb;
78
79 /* we don't do packed 24bpp */ 71 /* we don't do packed 24bpp */
80 if (sizes->surface_bpp == 24) 72 if (sizes->surface_bpp == 24)
81 sizes->surface_bpp = 32; 73 sizes->surface_bpp = 32;
@@ -102,13 +94,17 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
102 /* Flush everything out, we'll be doing GTT only from now on */ 94 /* Flush everything out, we'll be doing GTT only from now on */
103 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL); 95 ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
104 if (ret) { 96 if (ret) {
105 DRM_ERROR("failed to pin fb: %d\n", ret); 97 DRM_ERROR("failed to pin obj: %d\n", ret);
106 goto out_unref; 98 goto out_unref;
107 } 99 }
108 100
109 ret = intel_framebuffer_init(dev, ifbdev->fb, &mode_cmd, obj); 101 fb = __intel_framebuffer_create(dev, &mode_cmd, obj);
110 if (ret) 102 if (IS_ERR(fb)) {
103 ret = PTR_ERR(fb);
111 goto out_unpin; 104 goto out_unpin;
105 }
106
107 ifbdev->fb = to_intel_framebuffer(fb);
112 108
113 return 0; 109 return 0;
114 110