int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_gem_context_destroy *args = data; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; int ret; if (!(dev->driver->driver_features & DRIVER_GEM)) return -ENODEV; ret = i915_mutex_lock_interruptible(dev); if (ret) return ret; ctx = i915_gem_context_get(file_priv, args->ctx_id); if (!ctx) { mutex_unlock(&dev->struct_mutex); return -ENOENT; } do_destroy(ctx); mutex_unlock(&dev->struct_mutex); DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); return 0; }
/** * i915_switch_context() - perform a GPU context switch. * @ring: ring for which we'll execute the context switch * @file_priv: file_priv associated with the context, may be NULL * @id: context id number * @seqno: sequence number by which the new context will be switched to * @flags: * * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, * it will have a refoucnt > 1. This allows us to destroy the context abstract * object while letting the normal object tracking destroy the backing BO. */ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_file *file, int to_id) { struct drm_i915_private *dev_priv = ring->dev->dev_private; struct i915_hw_context *to; if (dev_priv->hw_contexts_disabled) return 0; if (ring != &dev_priv->rings[RCS]) return 0; if (to_id == DEFAULT_CONTEXT_ID) { to = ring->default_context; } else { if (file == NULL) return -EINVAL; to = i915_gem_context_get(file->driver_priv, to_id); if (to == NULL) return -ENOENT; } return do_switch(to); }
/** * i915_switch_context() - perform a GPU context switch. * @ring: ring for which we'll execute the context switch * @file_priv: file_priv associated with the context, may be NULL * @id: context id number * @seqno: sequence number by which the new context will be switched to * @flags: * * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, * it will have a refoucnt > 1. This allows us to destroy the context abstract * object while letting the normal object tracking destroy the backing BO. */ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_file *file, int to_id) { struct drm_i915_private *dev_priv = ring->dev->dev_private; struct drm_i915_file_private *file_priv = NULL; struct i915_hw_context *to; struct drm_i915_gem_object *from_obj = ring->last_context_obj; if (dev_priv->hw_contexts_disabled) return 0; if (ring != &dev_priv->ring[RCS]) return 0; if (file) file_priv = file->driver_priv; if (to_id == DEFAULT_CONTEXT_ID) { to = ring->default_context; } else { to = i915_gem_context_get(file_priv, to_id); if (to == NULL) return -ENOENT; } if (from_obj == to->obj) return 0; return do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring)); }
struct i915_ctx_hang_stats * i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring, struct drm_file *file, u32 id) { struct drm_i915_private *dev_priv = ring->dev->dev_private; struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *to; if (dev_priv->hw_contexts_disabled) return ERR_PTR(-ENOENT); if (ring->id != RCS) return ERR_PTR(-EINVAL); if (file == NULL) return ERR_PTR(-EINVAL); if (id == DEFAULT_CONTEXT_ID) return &file_priv->hang_stats; to = i915_gem_context_get(file->driver_priv, id); if (to == NULL) return ERR_PTR(-ENOENT); return &to->hang_stats; }
/** * i915_switch_context() - perform a GPU context switch. * @ring: ring for which we'll execute the context switch * @file_priv: file_priv associated with the context, may be NULL * @id: context id number * * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, * it will have a refoucnt > 1. This allows us to destroy the context abstract * object while letting the normal object tracking destroy the backing BO. */ int i915_switch_context(struct intel_ring_buffer *ring, struct drm_file *file, int to_id) { struct drm_i915_private *dev_priv = ring->dev->dev_private; struct i915_hw_context *to; if (!HAS_HW_CONTEXTS(ring->dev)) return 0; WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); if (ring != &dev_priv->ring[RCS]) return 0; if (to_id == DEFAULT_CONTEXT_ID) { to = ring->default_context; } else { if (file == NULL) return -EINVAL; to = i915_gem_context_get(file->driver_priv, to_id); if (to == NULL) return -ENOENT; } return do_switch(to); }
int __intel_context_do_pin(struct intel_context *ce) { int err; if (mutex_lock_interruptible(&ce->pin_mutex)) return -EINTR; if (likely(!atomic_read(&ce->pin_count))) { intel_wakeref_t wakeref; err = 0; with_intel_runtime_pm(ce->engine->i915, wakeref) err = ce->ops->pin(ce); if (err) goto err; i915_gem_context_get(ce->gem_context); /* for ctx->ppgtt */ intel_context_get(ce); smp_mb__before_atomic(); /* flush pin before it is visible */ } atomic_inc(&ce->pin_count); GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ mutex_unlock(&ce->pin_mutex); return 0; err: mutex_unlock(&ce->pin_mutex); return err; }
struct i915_ctx_hang_stats * i915_gem_context_get_hang_stats(struct drm_device *dev, struct drm_file *file, u32 id) { struct drm_i915_file_private *file_priv = file->driver_priv; struct i915_hw_context *ctx; if (id == DEFAULT_CONTEXT_ID) return &file_priv->hang_stats; if (!HAS_HW_CONTEXTS(dev)) return ERR_PTR(-ENOENT); ctx = i915_gem_context_get(file->driver_priv, id); if (ctx == NULL) return ERR_PTR(-ENOENT); return &ctx->hang_stats; }
int i915_get_reset_stats_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_reset_stats *args = data; struct i915_ctx_hang_stats *hs; struct intel_context *ctx; int ret; if (args->flags || args->pad) return -EINVAL; if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN)) return -EPERM; ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; ctx = i915_gem_context_get(file->driver_priv, args->ctx_id); if (IS_ERR(ctx)) { mutex_unlock(&dev->struct_mutex); return PTR_ERR(ctx); } hs = &ctx->hang_stats; if (capable(CAP_SYS_ADMIN)) args->reset_count = i915_reset_count(&dev_priv->gpu_error); else args->reset_count = 0; args->batch_active = hs->batch_active; args->batch_pending = hs->batch_pending; mutex_unlock(&dev->struct_mutex); return 0; }