1271705Sdumbbell/* 2271705Sdumbbell * Copyright �� 2011-2012 Intel Corporation 3271705Sdumbbell * 4271705Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 5271705Sdumbbell * copy of this software and associated documentation files (the "Software"), 6271705Sdumbbell * to deal in the Software without restriction, including without limitation 7271705Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8271705Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 9271705Sdumbbell * Software is furnished to do so, subject to the following conditions: 10271705Sdumbbell * 11271705Sdumbbell * The above copyright notice and this permission notice (including the next 12271705Sdumbbell * paragraph) shall be included in all copies or substantial portions of the 13271705Sdumbbell * Software. 14271705Sdumbbell * 15271705Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16271705Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17271705Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18271705Sdumbbell * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19271705Sdumbbell * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20271705Sdumbbell * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21271705Sdumbbell * IN THE SOFTWARE. 22271705Sdumbbell * 23271705Sdumbbell * Authors: 24271705Sdumbbell * Ben Widawsky <ben@bwidawsk.net> 25271705Sdumbbell * 26271705Sdumbbell */ 27271705Sdumbbell 28271705Sdumbbell/* 29271705Sdumbbell * This file implements HW context support. On gen5+ a HW context consists of an 30271705Sdumbbell * opaque GPU object which is referenced at times of context saves and restores. 31271705Sdumbbell * With RC6 enabled, the context is also referenced as the GPU enters and exists 32271705Sdumbbell * from RC6 (GPU has it's own internal power context, except on gen5). Though 33271705Sdumbbell * something like a context does exist for the media ring, the code only 34271705Sdumbbell * supports contexts for the render ring. 35271705Sdumbbell * 36271705Sdumbbell * In software, there is a distinction between contexts created by the user, 37271705Sdumbbell * and the default HW context. The default HW context is used by GPU clients 38271705Sdumbbell * that do not request setup of their own hardware context. The default 39271705Sdumbbell * context's state is never restored to help prevent programming errors. This 40271705Sdumbbell * would happen if a client ran and piggy-backed off another clients GPU state. 41271705Sdumbbell * The default context only exists to give the GPU some offset to load as the 42271705Sdumbbell * current to invoke a save of the context we actually care about. In fact, the 43271705Sdumbbell * code could likely be constructed, albeit in a more complicated fashion, to 44271705Sdumbbell * never use the default context, though that limits the driver's ability to 45271705Sdumbbell * swap out, and/or destroy other contexts. 46271705Sdumbbell * 47271705Sdumbbell * All other contexts are created as a request by the GPU client. These contexts 48271705Sdumbbell * store GPU state, and thus allow GPU clients to not re-emit state (and 49271705Sdumbbell * potentially query certain state) at any time. The kernel driver makes 50271705Sdumbbell * certain that the appropriate commands are inserted. 51271705Sdumbbell * 52271705Sdumbbell * The context life cycle is semi-complicated in that context BOs may live 53271705Sdumbbell * longer than the context itself because of the way the hardware, and object 54271705Sdumbbell * tracking works. Below is a very crude representation of the state machine 55271705Sdumbbell * describing the context life. 56271705Sdumbbell * refcount pincount active 57271705Sdumbbell * S0: initial state 0 0 0 58271705Sdumbbell * S1: context created 1 0 0 59271705Sdumbbell * S2: context is currently running 2 1 X 60271705Sdumbbell * S3: GPU referenced, but not current 2 0 1 61271705Sdumbbell * S4: context is current, but destroyed 1 1 0 62271705Sdumbbell * S5: like S3, but destroyed 1 0 1 63271705Sdumbbell * 64271705Sdumbbell * The most common (but not all) transitions: 65271705Sdumbbell * S0->S1: client creates a context 66271705Sdumbbell * S1->S2: client submits execbuf with context 67271705Sdumbbell * S2->S3: other clients submits execbuf with context 68271705Sdumbbell * S3->S1: context object was retired 69271705Sdumbbell * S3->S2: clients submits another execbuf 70271705Sdumbbell * S2->S4: context destroy called with current context 71271705Sdumbbell * S3->S5->S0: destroy path 72271705Sdumbbell * S4->S5->S0: destroy path on current context 73271705Sdumbbell * 74271705Sdumbbell * There are two confusing terms used above: 75271705Sdumbbell * The "current context" means the context which is currently running on the 76271705Sdumbbell * GPU. The GPU has loaded it's state already and has stored away the gtt 77271705Sdumbbell * offset of the BO. The GPU is not actively referencing the data at this 78271705Sdumbbell * offset, but it will on the next context switch. The only way to avoid this 79271705Sdumbbell * is to do a GPU reset. 80271705Sdumbbell * 81271705Sdumbbell * An "active context' is one which was previously the "current context" and is 82271705Sdumbbell * on the active list waiting for the next context switch to occur. Until this 83271705Sdumbbell * happens, the object must remain at the same gtt offset. It is therefore 84271705Sdumbbell * possible to destroy a context, but it is still active. 85271705Sdumbbell * 86271705Sdumbbell */ 87271705Sdumbbell 88271705Sdumbbell#include <sys/cdefs.h> 89271705Sdumbbell__FBSDID("$FreeBSD$"); 90271705Sdumbbell 91271705Sdumbbell#include <dev/drm2/drmP.h> 92271705Sdumbbell#include <dev/drm2/i915/i915_drm.h> 93271705Sdumbbell#include "i915_drv.h" 94271705Sdumbbell 95271705Sdumbbell/* This is a HW constraint. The value below is the largest known requirement 96271705Sdumbbell * I've seen in a spec to date, and that was a workaround for a non-shipping 97271705Sdumbbell * part. It should be safe to decrease this, but it's more future proof as is. 98271705Sdumbbell */ 99271705Sdumbbell#define CONTEXT_ALIGN (64<<10) 100271705Sdumbbell 101271705Sdumbbellstatic struct i915_hw_context * 102271705Sdumbbelli915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); 103271705Sdumbbellstatic int do_switch(struct i915_hw_context *to); 104271705Sdumbbell 105271705Sdumbbellstatic int get_context_size(struct drm_device *dev) 106271705Sdumbbell{ 107271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 108271705Sdumbbell int ret; 109271705Sdumbbell u32 reg; 110271705Sdumbbell 111271705Sdumbbell switch (INTEL_INFO(dev)->gen) { 112271705Sdumbbell case 6: 113271705Sdumbbell reg = I915_READ(CXT_SIZE); 114271705Sdumbbell ret = GEN6_CXT_TOTAL_SIZE(reg) * 64; 115271705Sdumbbell break; 116271705Sdumbbell case 7: 117271705Sdumbbell reg = I915_READ(GEN7_CXT_SIZE); 118271705Sdumbbell if (IS_HASWELL(dev)) 119271705Sdumbbell ret = HSW_CXT_TOTAL_SIZE(reg) * 64; 120271705Sdumbbell else 121271705Sdumbbell ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; 122271705Sdumbbell break; 123271705Sdumbbell default: 124271705Sdumbbell panic("i915_gem_context: Unsupported Intel GPU generation %d", 125271705Sdumbbell INTEL_INFO(dev)->gen); 126271705Sdumbbell } 127271705Sdumbbell 128271705Sdumbbell return ret; 129271705Sdumbbell} 130271705Sdumbbell 131271705Sdumbbellstatic void do_destroy(struct i915_hw_context *ctx) 132271705Sdumbbell{ 133271705Sdumbbell#if defined(INVARIANTS) 134271705Sdumbbell struct drm_device *dev = ctx->obj->base.dev; 135271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 136271705Sdumbbell#endif 137271705Sdumbbell 138271705Sdumbbell if (ctx->file_priv) 139271705Sdumbbell drm_gem_names_remove(&ctx->file_priv->context_idr, ctx->id); 140271705Sdumbbell else 141296548Sdumbbell KASSERT(ctx == dev_priv->ring[RCS].default_context, 142271705Sdumbbell ("i915_gem_context: ctx != default_context")); 143271705Sdumbbell 144271705Sdumbbell drm_gem_object_unreference(&ctx->obj->base); 145271705Sdumbbell free(ctx, DRM_I915_GEM); 146271705Sdumbbell} 147271705Sdumbbell 148271705Sdumbbellstatic int 149271705Sdumbbellcreate_hw_context(struct drm_device *dev, 150271705Sdumbbell struct drm_i915_file_private *file_priv, 151271705Sdumbbell struct i915_hw_context **ret_ctx) 152271705Sdumbbell{ 153271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 154271705Sdumbbell struct i915_hw_context *ctx; 155271705Sdumbbell int ret, id; 156271705Sdumbbell 157271705Sdumbbell ctx = malloc(sizeof(*ctx), DRM_I915_GEM, M_NOWAIT | M_ZERO); 158271705Sdumbbell if (ctx == NULL) 159271705Sdumbbell return (-ENOMEM); 160271705Sdumbbell 161271705Sdumbbell ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); 162271705Sdumbbell if (ctx->obj == NULL) { 163271705Sdumbbell free(ctx, DRM_I915_GEM); 164271705Sdumbbell DRM_DEBUG_DRIVER("Context object allocated failed\n"); 165271705Sdumbbell return (-ENOMEM); 166271705Sdumbbell } 167271705Sdumbbell 168271705Sdumbbell if (INTEL_INFO(dev)->gen >= 7) { 169271705Sdumbbell ret = i915_gem_object_set_cache_level(ctx->obj, 170271705Sdumbbell I915_CACHE_LLC_MLC); 171271705Sdumbbell if (ret) 172271705Sdumbbell goto err_out; 173271705Sdumbbell } 174271705Sdumbbell 175271705Sdumbbell /* The ring associated with the context object is handled by the normal 176271705Sdumbbell * object tracking code. We give an initial ring value simple to pass an 177271705Sdumbbell * assertion in the context switch code. 178271705Sdumbbell */ 179296548Sdumbbell ctx->ring = &dev_priv->ring[RCS]; 180271705Sdumbbell 181271705Sdumbbell /* Default context will never have a file_priv */ 182271705Sdumbbell if (file_priv == NULL) { 183271705Sdumbbell *ret_ctx = ctx; 184271705Sdumbbell return (0); 185271705Sdumbbell } 186271705Sdumbbell 187271705Sdumbbell ctx->file_priv = file_priv; 188271705Sdumbbell 189271705Sdumbbellagain: 190271705Sdumbbell id = 0; 191271705Sdumbbell ret = drm_gem_name_create(&file_priv->context_idr, ctx, &id); 192271705Sdumbbell if (ret == 0) 193271705Sdumbbell ctx->id = id; 194271705Sdumbbell 195271705Sdumbbell if (ret == -EAGAIN) 196271705Sdumbbell goto again; 197271705Sdumbbell else if (ret) 198271705Sdumbbell goto err_out; 199271705Sdumbbell 200271705Sdumbbell *ret_ctx = ctx; 201271705Sdumbbell return (0); 202271705Sdumbbell 203271705Sdumbbellerr_out: 204271705Sdumbbell do_destroy(ctx); 205271705Sdumbbell return (ret); 206271705Sdumbbell} 207271705Sdumbbell 208271705Sdumbbellstatic inline bool is_default_context(struct i915_hw_context *ctx) 209271705Sdumbbell{ 210271705Sdumbbell return (ctx == ctx->ring->default_context); 211271705Sdumbbell} 212271705Sdumbbell 213271705Sdumbbell/** 214271705Sdumbbell * The default context needs to exist per ring that uses contexts. It stores the 215271705Sdumbbell * context state of the GPU for applications that don't utilize HW contexts, as 216271705Sdumbbell * well as an idle case. 217271705Sdumbbell */ 218271705Sdumbbellstatic int create_default_context(struct drm_i915_private *dev_priv) 219271705Sdumbbell{ 220271705Sdumbbell struct i915_hw_context *ctx; 221271705Sdumbbell int ret; 222271705Sdumbbell 223271705Sdumbbell DRM_LOCK_ASSERT(dev_priv->dev); 224271705Sdumbbell 225271705Sdumbbell ret = create_hw_context(dev_priv->dev, NULL, &ctx); 226271705Sdumbbell if (ret != 0) 227271705Sdumbbell return (ret); 228271705Sdumbbell 229271705Sdumbbell /* We may need to do things with the shrinker which require us to 230271705Sdumbbell * immediately switch back to the default context. This can cause a 231271705Sdumbbell * problem as pinning the default context also requires GTT space which 232271705Sdumbbell * may not be available. To avoid this we always pin the 233271705Sdumbbell * default context. 234271705Sdumbbell */ 235296548Sdumbbell dev_priv->ring[RCS].default_context = ctx; 236296548Sdumbbell ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false, false); 237271705Sdumbbell if (ret) 238271705Sdumbbell goto err_destroy; 239271705Sdumbbell 240271705Sdumbbell ret = do_switch(ctx); 241271705Sdumbbell if (ret) 242271705Sdumbbell goto err_unpin; 243271705Sdumbbell 244271705Sdumbbell DRM_DEBUG_DRIVER("Default HW context loaded\n"); 245271705Sdumbbell return 0; 246271705Sdumbbell 247271705Sdumbbellerr_unpin: 248271705Sdumbbell i915_gem_object_unpin(ctx->obj); 249271705Sdumbbellerr_destroy: 250271705Sdumbbell do_destroy(ctx); 251271705Sdumbbell return ret; 252271705Sdumbbell} 253271705Sdumbbell 254271705Sdumbbellvoid i915_gem_context_init(struct drm_device *dev) 255271705Sdumbbell{ 256271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 257271705Sdumbbell uint32_t ctx_size; 258271705Sdumbbell 259271705Sdumbbell if (!HAS_HW_CONTEXTS(dev)) { 260271705Sdumbbell dev_priv->hw_contexts_disabled = true; 261271705Sdumbbell return; 262271705Sdumbbell } 263271705Sdumbbell 264271705Sdumbbell /* If called from reset, or thaw... we've been here already */ 265271705Sdumbbell if (dev_priv->hw_contexts_disabled || 266296548Sdumbbell dev_priv->ring[RCS].default_context) 267271705Sdumbbell return; 268271705Sdumbbell 269271705Sdumbbell ctx_size = get_context_size(dev); 270271705Sdumbbell dev_priv->hw_context_size = get_context_size(dev); 271296548Sdumbbell dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096); 272271705Sdumbbell 273271705Sdumbbell if (ctx_size <= 0 || ctx_size > (1<<20)) { 274271705Sdumbbell dev_priv->hw_contexts_disabled = true; 275271705Sdumbbell return; 276271705Sdumbbell } 277271705Sdumbbell 278271705Sdumbbell if (create_default_context(dev_priv)) { 279271705Sdumbbell dev_priv->hw_contexts_disabled = true; 280271705Sdumbbell return; 281271705Sdumbbell } 282271705Sdumbbell 283271705Sdumbbell DRM_DEBUG_DRIVER("HW context support initialized\n"); 284271705Sdumbbell} 285271705Sdumbbell 286271705Sdumbbellvoid i915_gem_context_fini(struct drm_device *dev) 287271705Sdumbbell{ 288271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 289271705Sdumbbell 290271705Sdumbbell if (dev_priv->hw_contexts_disabled) 291271705Sdumbbell return; 292271705Sdumbbell 293271705Sdumbbell /* The only known way to stop the gpu from accessing the hw context is 294271705Sdumbbell * to reset it. Do this as the very last operation to avoid confusing 295271705Sdumbbell * other code, leading to spurious errors. */ 296271705Sdumbbell intel_gpu_reset(dev); 297271705Sdumbbell 298296548Sdumbbell i915_gem_object_unpin(dev_priv->ring[RCS].default_context->obj); 299271705Sdumbbell 300296768Sdumbbell /* When default context is created and switched to, base object refcount 301296768Sdumbbell * will be 2 (+1 from object creation and +1 from do_switch()). 302296768Sdumbbell * i915_gem_context_fini() will be called after gpu_idle() has switched 303296768Sdumbbell * to default context. So we need to unreference the base object once 304296768Sdumbbell * to offset the do_switch part, so that i915_gem_context_unreference() 305296768Sdumbbell * can then free the base object correctly. */ 306296768Sdumbbell drm_gem_object_unreference(&dev_priv->ring[RCS].default_context->obj->base); 307296768Sdumbbell 308296548Sdumbbell do_destroy(dev_priv->ring[RCS].default_context); 309271705Sdumbbell} 310271705Sdumbbell 311287175Sbaptstatic int context_idr_cleanup(uint32_t id, void *p, void *data) 312271705Sdumbbell{ 313271705Sdumbbell struct i915_hw_context *ctx = p; 314271705Sdumbbell 315271705Sdumbbell KASSERT(id != DEFAULT_CONTEXT_ID, ("i915_gem_context: id == DEFAULT_CONTEXT_ID in cleanup")); 316271705Sdumbbell 317271705Sdumbbell do_destroy(ctx); 318271705Sdumbbell 319271705Sdumbbell return 0; 320271705Sdumbbell} 321271705Sdumbbell 322271705Sdumbbellvoid i915_gem_context_close(struct drm_device *dev, struct drm_file *file) 323271705Sdumbbell{ 324271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 325271705Sdumbbell 326280183Sdumbbell DRM_LOCK(dev); 327271705Sdumbbell drm_gem_names_foreach(&file_priv->context_idr, context_idr_cleanup, NULL); 328271705Sdumbbell drm_gem_names_fini(&file_priv->context_idr); 329280183Sdumbbell DRM_UNLOCK(dev); 330271705Sdumbbell} 331271705Sdumbbell 332271705Sdumbbellstatic struct i915_hw_context * 333271705Sdumbbelli915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) 334271705Sdumbbell{ 335271705Sdumbbell return (struct i915_hw_context *)drm_gem_find_ptr(&file_priv->context_idr, id); 336271705Sdumbbell} 337271705Sdumbbell 338271705Sdumbbellstatic inline int 339271705Sdumbbellmi_set_context(struct intel_ring_buffer *ring, 340271705Sdumbbell struct i915_hw_context *new_context, 341271705Sdumbbell u32 hw_flags) 342271705Sdumbbell{ 343271705Sdumbbell int ret; 344271705Sdumbbell 345271705Sdumbbell /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB 346271705Sdumbbell * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value 347271705Sdumbbell * explicitly, so we rely on the value at ring init, stored in 348271705Sdumbbell * itlb_before_ctx_switch. 349271705Sdumbbell */ 350271705Sdumbbell if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { 351271705Sdumbbell ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0); 352271705Sdumbbell if (ret) 353271705Sdumbbell return ret; 354271705Sdumbbell } 355271705Sdumbbell 356271705Sdumbbell ret = intel_ring_begin(ring, 6); 357271705Sdumbbell if (ret) 358271705Sdumbbell return ret; 359271705Sdumbbell 360271705Sdumbbell if (IS_GEN7(ring->dev)) 361271705Sdumbbell intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); 362271705Sdumbbell else 363271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 364271705Sdumbbell 365271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 366271705Sdumbbell intel_ring_emit(ring, MI_SET_CONTEXT); 367271705Sdumbbell intel_ring_emit(ring, new_context->obj->gtt_offset | 368271705Sdumbbell MI_MM_SPACE_GTT | 369271705Sdumbbell MI_SAVE_EXT_STATE_EN | 370271705Sdumbbell MI_RESTORE_EXT_STATE_EN | 371271705Sdumbbell hw_flags); 372271705Sdumbbell /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ 373271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 374271705Sdumbbell 375271705Sdumbbell if (IS_GEN7(ring->dev)) 376271705Sdumbbell intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); 377271705Sdumbbell else 378271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 379271705Sdumbbell 380271705Sdumbbell intel_ring_advance(ring); 381271705Sdumbbell 382271705Sdumbbell return ret; 383271705Sdumbbell} 384271705Sdumbbell 385271705Sdumbbellstatic int do_switch(struct i915_hw_context *to) 386271705Sdumbbell{ 387271705Sdumbbell struct intel_ring_buffer *ring = to->ring; 388271705Sdumbbell struct drm_i915_gem_object *from_obj = ring->last_context_obj; 389271705Sdumbbell u32 hw_flags = 0; 390271705Sdumbbell int ret; 391271705Sdumbbell 392271705Sdumbbell KASSERT(!(from_obj != NULL && from_obj->pin_count == 0), 393271705Sdumbbell ("i915_gem_context: invalid \"from\" context")); 394271705Sdumbbell 395271705Sdumbbell if (from_obj == to->obj) 396271705Sdumbbell return 0; 397271705Sdumbbell 398296548Sdumbbell ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false, false); 399271705Sdumbbell if (ret) 400271705Sdumbbell return ret; 401271705Sdumbbell 402271705Sdumbbell /* Clear this page out of any CPU caches for coherent swap-in/out. Note 403271705Sdumbbell * that thanks to write = false in this call and us not setting any gpu 404271705Sdumbbell * write domains when putting a context object onto the active list 405271705Sdumbbell * (when switching away from it), this won't block. 406271705Sdumbbell * XXX: We need a real interface to do this instead of trickery. */ 407271705Sdumbbell ret = i915_gem_object_set_to_gtt_domain(to->obj, false); 408271705Sdumbbell if (ret) { 409271705Sdumbbell i915_gem_object_unpin(to->obj); 410271705Sdumbbell return ret; 411271705Sdumbbell } 412271705Sdumbbell 413271705Sdumbbell if (!to->obj->has_global_gtt_mapping) 414277487Skib i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); 415271705Sdumbbell 416271705Sdumbbell if (!to->is_initialized || is_default_context(to)) 417271705Sdumbbell hw_flags |= MI_RESTORE_INHIBIT; 418271705Sdumbbell else if (from_obj == to->obj) /* not yet expected */ 419271705Sdumbbell hw_flags |= MI_FORCE_RESTORE; 420271705Sdumbbell 421271705Sdumbbell ret = mi_set_context(ring, to, hw_flags); 422271705Sdumbbell if (ret) { 423271705Sdumbbell i915_gem_object_unpin(to->obj); 424271705Sdumbbell return ret; 425271705Sdumbbell } 426271705Sdumbbell 427271705Sdumbbell /* The backing object for the context is done after switching to the 428271705Sdumbbell * *next* context. Therefore we cannot retire the previous context until 429271705Sdumbbell * the next context has already started running. In fact, the below code 430271705Sdumbbell * is a bit suboptimal because the retiring can occur simply after the 431271705Sdumbbell * MI_SET_CONTEXT instead of when the next seqno has completed. 432271705Sdumbbell */ 433271705Sdumbbell if (from_obj != NULL) { 434271705Sdumbbell from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; 435296548Sdumbbell i915_gem_object_move_to_active(from_obj, ring); 436271705Sdumbbell /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the 437271705Sdumbbell * whole damn pipeline, we don't need to explicitly mark the 438271705Sdumbbell * object dirty. The only exception is that the context must be 439271705Sdumbbell * correct in case the object gets swapped out. Ideally we'd be 440271705Sdumbbell * able to defer doing this until we know the object would be 441271705Sdumbbell * swapped, but there is no way to do that yet. 442271705Sdumbbell */ 443271705Sdumbbell from_obj->dirty = 1; 444271705Sdumbbell KASSERT(from_obj->ring == ring, ("i915_gem_context: from_ring != ring")); 445271705Sdumbbell i915_gem_object_unpin(from_obj); 446271705Sdumbbell 447271705Sdumbbell drm_gem_object_unreference(&from_obj->base); 448271705Sdumbbell } 449271705Sdumbbell 450271705Sdumbbell drm_gem_object_reference(&to->obj->base); 451271705Sdumbbell ring->last_context_obj = to->obj; 452271705Sdumbbell to->is_initialized = true; 453271705Sdumbbell 454271705Sdumbbell return 0; 455271705Sdumbbell} 456271705Sdumbbell 457271705Sdumbbell/** 458271705Sdumbbell * i915_switch_context() - perform a GPU context switch. 459271705Sdumbbell * @ring: ring for which we'll execute the context switch 460271705Sdumbbell * @file_priv: file_priv associated with the context, may be NULL 461271705Sdumbbell * @id: context id number 462271705Sdumbbell * @seqno: sequence number by which the new context will be switched to 463271705Sdumbbell * @flags: 464271705Sdumbbell * 465271705Sdumbbell * The context life cycle is simple. The context refcount is incremented and 466271705Sdumbbell * decremented by 1 and create and destroy. If the context is in use by the GPU, 467271705Sdumbbell * it will have a refoucnt > 1. This allows us to destroy the context abstract 468271705Sdumbbell * object while letting the normal object tracking destroy the backing BO. 469271705Sdumbbell */ 470271705Sdumbbellint i915_switch_context(struct intel_ring_buffer *ring, 471271705Sdumbbell struct drm_file *file, 472271705Sdumbbell int to_id) 473271705Sdumbbell{ 474271705Sdumbbell struct drm_i915_private *dev_priv = ring->dev->dev_private; 475271705Sdumbbell struct i915_hw_context *to; 476271705Sdumbbell 477271705Sdumbbell if (dev_priv->hw_contexts_disabled) 478271705Sdumbbell return 0; 479271705Sdumbbell 480296548Sdumbbell if (ring != &dev_priv->ring[RCS]) 481271705Sdumbbell return 0; 482271705Sdumbbell 483271705Sdumbbell if (to_id == DEFAULT_CONTEXT_ID) { 484271705Sdumbbell to = ring->default_context; 485271705Sdumbbell } else { 486271705Sdumbbell if (file == NULL) 487271705Sdumbbell return -EINVAL; 488271705Sdumbbell 489271705Sdumbbell to = i915_gem_context_get(file->driver_priv, to_id); 490271705Sdumbbell if (to == NULL) 491271705Sdumbbell return -ENOENT; 492271705Sdumbbell } 493271705Sdumbbell 494271705Sdumbbell return do_switch(to); 495271705Sdumbbell} 496271705Sdumbbell 497271705Sdumbbellint i915_gem_context_create_ioctl(struct drm_device *dev, void *data, 498271705Sdumbbell struct drm_file *file) 499271705Sdumbbell{ 500271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 501271705Sdumbbell struct drm_i915_gem_context_create *args = data; 502271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 503271705Sdumbbell struct i915_hw_context *ctx; 504271705Sdumbbell int ret; 505271705Sdumbbell 506271705Sdumbbell if (!(dev->driver->driver_features & DRIVER_GEM)) 507271705Sdumbbell return -ENODEV; 508271705Sdumbbell 509271705Sdumbbell if (dev_priv->hw_contexts_disabled) 510271705Sdumbbell return -ENODEV; 511271705Sdumbbell 512271705Sdumbbell ret = i915_mutex_lock_interruptible(dev); 513271705Sdumbbell if (ret) 514271705Sdumbbell return ret; 515271705Sdumbbell 516271705Sdumbbell ret = create_hw_context(dev, file_priv, &ctx); 517271705Sdumbbell DRM_UNLOCK(dev); 518271705Sdumbbell if (ret != 0) 519271705Sdumbbell return (ret); 520271705Sdumbbell 521271705Sdumbbell args->ctx_id = ctx->id; 522271705Sdumbbell DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); 523271705Sdumbbell 524271705Sdumbbell return 0; 525271705Sdumbbell} 526271705Sdumbbell 527271705Sdumbbellint i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, 528271705Sdumbbell struct drm_file *file) 529271705Sdumbbell{ 530271705Sdumbbell struct drm_i915_gem_context_destroy *args = data; 531271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 532271705Sdumbbell struct i915_hw_context *ctx; 533271705Sdumbbell int ret; 534271705Sdumbbell 535271705Sdumbbell if (!(dev->driver->driver_features & DRIVER_GEM)) 536271705Sdumbbell return -ENODEV; 537271705Sdumbbell 538271705Sdumbbell ret = i915_mutex_lock_interruptible(dev); 539271705Sdumbbell if (ret) 540271705Sdumbbell return ret; 541271705Sdumbbell 542271705Sdumbbell ctx = i915_gem_context_get(file_priv, args->ctx_id); 543271705Sdumbbell if (!ctx) { 544271705Sdumbbell DRM_UNLOCK(dev); 545271705Sdumbbell return -ENOENT; 546271705Sdumbbell } 547271705Sdumbbell 548271705Sdumbbell do_destroy(ctx); 549271705Sdumbbell 550271705Sdumbbell DRM_UNLOCK(dev); 551271705Sdumbbell 552271705Sdumbbell DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); 553271705Sdumbbell return 0; 554271705Sdumbbell} 555