diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 92 |
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); |