Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/gma500/psb: Fix cursor gem obj referencing on psb

The internal crtc cursor gem object pointer was never set/updated since
it was required to be set in the first place.

Fixing this will make the pin/unpin count match and prevent cursor
objects from leaking when userspace drops all references to it. Also
make sure we drop the gem obj reference on failure.

This patch only affects Poulsbo chips.

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>

+13 -6
+13 -6
drivers/gpu/drm/gma500/psb_intel_display.c
··· 843 843 struct gtt_range *cursor_gt = psb_intel_crtc->cursor_gt; 844 844 struct drm_gem_object *obj; 845 845 void *tmp_dst, *tmp_src; 846 - int ret, i, cursor_pages; 846 + int ret = 0, i, cursor_pages; 847 847 848 848 /* if we want to turn of the cursor ignore width and height */ 849 849 if (!handle) { ··· 880 880 881 881 if (obj->size < width * height * 4) { 882 882 dev_dbg(dev->dev, "buffer is to small\n"); 883 - return -ENOMEM; 883 + ret = -ENOMEM; 884 + goto unref_cursor; 884 885 } 885 886 886 887 gt = container_of(obj, struct gtt_range, gem); ··· 890 889 ret = psb_gtt_pin(gt); 891 890 if (ret) { 892 891 dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); 893 - return ret; 892 + goto unref_cursor; 894 893 } 895 894 896 895 if (dev_priv->ops->cursor_needs_phys) { 897 896 if (cursor_gt == NULL) { 898 897 dev_err(dev->dev, "No hardware cursor mem available"); 899 - return -ENOMEM; 898 + ret = -ENOMEM; 899 + goto unref_cursor; 900 900 } 901 901 902 902 /* Prevent overflow */ ··· 938 936 struct gtt_range, gem); 939 937 psb_gtt_unpin(gt); 940 938 drm_gem_object_unreference(psb_intel_crtc->cursor_obj); 941 - psb_intel_crtc->cursor_obj = obj; 942 939 } 943 - return 0; 940 + 941 + psb_intel_crtc->cursor_obj = obj; 942 + return ret; 943 + 944 + unref_cursor: 945 + drm_gem_object_unreference(obj); 946 + return ret; 944 947 } 945 948 946 949 static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)