diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-02-10 12:00:39 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-02-12 12:53:02 -0500 |
commit | a8bb6818270c32126dba0fd2ddb139d885c5687d (patch) | |
tree | 56f0b21a168e442a3000cb517a93b84dba7ceacf | |
parent | ef2d633e9bcfdb73e536ca81b835dd015fe24ceb (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.c | 35 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_fbdev.c | 20 |
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 | ||
7693 | static struct drm_framebuffer * | 7693 | static int intel_framebuffer_init(struct drm_device *dev, |
7694 | intel_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 | |||
7698 | struct 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 | ||
7724 | struct drm_framebuffer * | ||
7725 | intel_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 | |||
7724 | static u32 | 7741 | static u32 |
7725 | intel_framebuffer_pitch_for_width(int width, int bpp) | 7742 | intel_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); |
683 | void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); | 683 | void intel_unpin_fb_obj(struct drm_i915_gem_object *obj); |
684 | int intel_framebuffer_init(struct drm_device *dev, | 684 | struct 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); |
688 | void intel_prepare_page_flip(struct drm_device *dev, int plane); | 688 | void 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 | ||