aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c92
1 files changed, 47 insertions, 45 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index c60ca32f65d2..dea9ac069851 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3128,6 +3128,21 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3128 } 3128 }
3129 target_obj_priv = target_obj->driver_private; 3129 target_obj_priv = target_obj->driver_private;
3130 3130
3131#if WATCH_RELOC
3132 DRM_INFO("%s: obj %p offset %08x target %d "
3133 "read %08x write %08x gtt %08x "
3134 "presumed %08x delta %08x\n",
3135 __func__,
3136 obj,
3137 (int) reloc->offset,
3138 (int) reloc->target_handle,
3139 (int) reloc->read_domains,
3140 (int) reloc->write_domain,
3141 (int) target_obj_priv->gtt_offset,
3142 (int) reloc->presumed_offset,
3143 reloc->delta);
3144#endif
3145
3131 /* The target buffer should have appeared before us in the 3146 /* The target buffer should have appeared before us in the
3132 * exec_object list, so it should have a GTT space bound by now. 3147 * exec_object list, so it should have a GTT space bound by now.
3133 */ 3148 */
@@ -3139,35 +3154,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3139 return -EINVAL; 3154 return -EINVAL;
3140 } 3155 }
3141 3156
3142 if (reloc->offset > obj->size - 4) { 3157 /* Validate that the target is in a valid r/w GPU domain */
3143 DRM_ERROR("Relocation beyond object bounds: "
3144 "obj %p target %d offset %d size %d.\n",
3145 obj, reloc->target_handle,
3146 (int) reloc->offset, (int) obj->size);
3147 drm_gem_object_unreference(target_obj);
3148 i915_gem_object_unpin(obj);
3149 return -EINVAL;
3150 }
3151 if (reloc->offset & 3) {
3152 DRM_ERROR("Relocation not 4-byte aligned: "
3153 "obj %p target %d offset %d.\n",
3154 obj, reloc->target_handle,
3155 (int) reloc->offset);
3156 drm_gem_object_unreference(target_obj);
3157 i915_gem_object_unpin(obj);
3158 return -EINVAL;
3159 }
3160
3161 if (reloc->delta >= target_obj->size) {
3162 DRM_ERROR("Relocation beyond target object bounds: "
3163 "obj %p target %d delta %d size %d.\n",
3164 obj, reloc->target_handle,
3165 (int) reloc->delta, (int) target_obj->size);
3166 drm_gem_object_unreference(target_obj);
3167 i915_gem_object_unpin(obj);
3168 return -EINVAL;
3169 }
3170
3171 if (reloc->write_domain & I915_GEM_DOMAIN_CPU || 3158 if (reloc->write_domain & I915_GEM_DOMAIN_CPU ||
3172 reloc->read_domains & I915_GEM_DOMAIN_CPU) { 3159 reloc->read_domains & I915_GEM_DOMAIN_CPU) {
3173 DRM_ERROR("reloc with read/write CPU domains: " 3160 DRM_ERROR("reloc with read/write CPU domains: "
@@ -3181,7 +3168,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3181 i915_gem_object_unpin(obj); 3168 i915_gem_object_unpin(obj);
3182 return -EINVAL; 3169 return -EINVAL;
3183 } 3170 }
3184
3185 if (reloc->write_domain && target_obj->pending_write_domain && 3171 if (reloc->write_domain && target_obj->pending_write_domain &&
3186 reloc->write_domain != target_obj->pending_write_domain) { 3172 reloc->write_domain != target_obj->pending_write_domain) {
3187 DRM_ERROR("Write domain conflict: " 3173 DRM_ERROR("Write domain conflict: "
@@ -3196,21 +3182,6 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3196 return -EINVAL; 3182 return -EINVAL;
3197 } 3183 }
3198 3184
3199#if WATCH_RELOC
3200 DRM_INFO("%s: obj %p offset %08x target %d "
3201 "read %08x write %08x gtt %08x "
3202 "presumed %08x delta %08x\n",
3203 __func__,
3204 obj,
3205 (int) reloc->offset,
3206 (int) reloc->target_handle,
3207 (int) reloc->read_domains,
3208 (int) reloc->write_domain,
3209 (int) target_obj_priv->gtt_offset,
3210 (int) reloc->presumed_offset,
3211 reloc->delta);
3212#endif
3213
3214 target_obj->pending_read_domains |= reloc->read_domains; 3185 target_obj->pending_read_domains |= reloc->read_domains;
3215 target_obj->pending_write_domain |= reloc->write_domain; 3186 target_obj->pending_write_domain |= reloc->write_domain;
3216 3187
@@ -3222,6 +3193,37 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
3222 continue; 3193 continue;
3223 } 3194 }
3224 3195
3196 /* Check that the relocation address is valid... */
3197 if (reloc->offset > obj->size - 4) {
3198 DRM_ERROR("Relocation beyond object bounds: "
3199 "obj %p target %d offset %d size %d.\n",
3200 obj, reloc->target_handle,
3201 (int) reloc->offset, (int) obj->size);
3202 drm_gem_object_unreference(target_obj);
3203 i915_gem_object_unpin(obj);
3204 return -EINVAL;
3205 }
3206 if (reloc->offset & 3) {
3207 DRM_ERROR("Relocation not 4-byte aligned: "
3208 "obj %p target %d offset %d.\n",
3209 obj, reloc->target_handle,
3210 (int) reloc->offset);
3211 drm_gem_object_unreference(target_obj);
3212 i915_gem_object_unpin(obj);
3213 return -EINVAL;
3214 }
3215
3216 /* and points to somewhere within the target object. */
3217 if (reloc->delta >= target_obj->size) {
3218 DRM_ERROR("Relocation beyond target object bounds: "
3219 "obj %p target %d delta %d size %d.\n",
3220 obj, reloc->target_handle,
3221 (int) reloc->delta, (int) target_obj->size);
3222 drm_gem_object_unreference(target_obj);
3223 i915_gem_object_unpin(obj);
3224 return -EINVAL;
3225 }
3226
3225 ret = i915_gem_object_set_to_gtt_domain(obj, 1); 3227 ret = i915_gem_object_set_to_gtt_domain(obj, 1);
3226 if (ret != 0) { 3228 if (ret != 0) {
3227 drm_gem_object_unreference(target_obj); 3229 drm_gem_object_unreference(target_obj);