diff options
author | Keith Packard <keithp@keithp.com> | 2008-11-21 02:30:27 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2008-12-03 20:22:06 -0500 |
commit | ac94a962b24a88ea5d00f4697550d9982f300751 (patch) | |
tree | 9dacd94c107aafc3eb33241f1aef0c8fa2dec923 | |
parent | 646f0f6e43bf6628b1f0f8ca6c0227ce72e8ef3c (diff) |
drm/i915: Retry execbuffer pinning after clearing the GTT
If we fail to pin all of the buffers in an execbuffer request, go through
and clear the GTT and try again to see if its just a matter of fragmentation
Signed-off-by: Keith Packard <keithp@keithp.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 57 |
1 files changed, 47 insertions, 10 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c171a2d93bb6..174c0c3ba0b0 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1088,6 +1088,19 @@ i915_gem_evict_something(struct drm_device *dev) | |||
1088 | } | 1088 | } |
1089 | 1089 | ||
1090 | static int | 1090 | static int |
1091 | i915_gem_evict_everything(struct drm_device *dev) | ||
1092 | { | ||
1093 | int ret; | ||
1094 | |||
1095 | for (;;) { | ||
1096 | ret = i915_gem_evict_something(dev); | ||
1097 | if (ret != 0) | ||
1098 | break; | ||
1099 | } | ||
1100 | return ret; | ||
1101 | } | ||
1102 | |||
1103 | static int | ||
1091 | i915_gem_object_get_page_list(struct drm_gem_object *obj) | 1104 | i915_gem_object_get_page_list(struct drm_gem_object *obj) |
1092 | { | 1105 | { |
1093 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | 1106 | struct drm_i915_gem_object *obj_priv = obj->driver_private; |
@@ -1173,7 +1186,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
1173 | 1186 | ||
1174 | ret = i915_gem_evict_something(dev); | 1187 | ret = i915_gem_evict_something(dev); |
1175 | if (ret != 0) { | 1188 | if (ret != 0) { |
1176 | DRM_ERROR("Failed to evict a buffer %d\n", ret); | 1189 | if (ret != -ERESTARTSYS) |
1190 | DRM_ERROR("Failed to evict a buffer %d\n", ret); | ||
1177 | return ret; | 1191 | return ret; |
1178 | } | 1192 | } |
1179 | goto search_free; | 1193 | goto search_free; |
@@ -1922,6 +1936,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1922 | int ret, i, pinned = 0; | 1936 | int ret, i, pinned = 0; |
1923 | uint64_t exec_offset; | 1937 | uint64_t exec_offset; |
1924 | uint32_t seqno, flush_domains; | 1938 | uint32_t seqno, flush_domains; |
1939 | int pin_tries; | ||
1925 | 1940 | ||
1926 | #if WATCH_EXEC | 1941 | #if WATCH_EXEC |
1927 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | 1942 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", |
@@ -1970,7 +1985,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1970 | return -EBUSY; | 1985 | return -EBUSY; |
1971 | } | 1986 | } |
1972 | 1987 | ||
1973 | /* Look up object handles and perform the relocations */ | 1988 | /* Look up object handles */ |
1974 | for (i = 0; i < args->buffer_count; i++) { | 1989 | for (i = 0; i < args->buffer_count; i++) { |
1975 | object_list[i] = drm_gem_object_lookup(dev, file_priv, | 1990 | object_list[i] = drm_gem_object_lookup(dev, file_priv, |
1976 | exec_list[i].handle); | 1991 | exec_list[i].handle); |
@@ -1980,17 +1995,39 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1980 | ret = -EBADF; | 1995 | ret = -EBADF; |
1981 | goto err; | 1996 | goto err; |
1982 | } | 1997 | } |
1998 | } | ||
1983 | 1999 | ||
1984 | object_list[i]->pending_read_domains = 0; | 2000 | /* Pin and relocate */ |
1985 | object_list[i]->pending_write_domain = 0; | 2001 | for (pin_tries = 0; ; pin_tries++) { |
1986 | ret = i915_gem_object_pin_and_relocate(object_list[i], | 2002 | ret = 0; |
1987 | file_priv, | 2003 | for (i = 0; i < args->buffer_count; i++) { |
1988 | &exec_list[i]); | 2004 | object_list[i]->pending_read_domains = 0; |
1989 | if (ret) { | 2005 | object_list[i]->pending_write_domain = 0; |
1990 | DRM_ERROR("object bind and relocate failed %d\n", ret); | 2006 | ret = i915_gem_object_pin_and_relocate(object_list[i], |
2007 | file_priv, | ||
2008 | &exec_list[i]); | ||
2009 | if (ret) | ||
2010 | break; | ||
2011 | pinned = i + 1; | ||
2012 | } | ||
2013 | /* success */ | ||
2014 | if (ret == 0) | ||
2015 | break; | ||
2016 | |||
2017 | /* error other than GTT full, or we've already tried again */ | ||
2018 | if (ret != -ENOMEM || pin_tries >= 1) { | ||
2019 | DRM_ERROR("Failed to pin buffers %d\n", ret); | ||
1991 | goto err; | 2020 | goto err; |
1992 | } | 2021 | } |
1993 | pinned = i + 1; | 2022 | |
2023 | /* unpin all of our buffers */ | ||
2024 | for (i = 0; i < pinned; i++) | ||
2025 | i915_gem_object_unpin(object_list[i]); | ||
2026 | |||
2027 | /* evict everyone we can from the aperture */ | ||
2028 | ret = i915_gem_evict_everything(dev); | ||
2029 | if (ret) | ||
2030 | goto err; | ||
1994 | } | 2031 | } |
1995 | 2032 | ||
1996 | /* Set the pending read domains for the batch buffer to COMMAND */ | 2033 | /* Set the pending read domains for the batch buffer to COMMAND */ |