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: releng/10.3/sys/dev/drm2/i915/i915_gem_context.c 282199 2015-04-28 19:35:05Z dumbbell $"); 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#ifdef FREEBSD_WIP 119271705Sdumbbell if (IS_HASWELL(dev)) 120271705Sdumbbell ret = HSW_CXT_TOTAL_SIZE(reg) * 64; 121271705Sdumbbell else 122271705Sdumbbell#endif 123271705Sdumbbell ret = GEN7_CXT_TOTAL_SIZE(reg) * 64; 124271705Sdumbbell break; 125271705Sdumbbell default: 126271705Sdumbbell panic("i915_gem_context: Unsupported Intel GPU generation %d", 127271705Sdumbbell INTEL_INFO(dev)->gen); 128271705Sdumbbell } 129271705Sdumbbell 130271705Sdumbbell return ret; 131271705Sdumbbell} 132271705Sdumbbell 133271705Sdumbbellstatic void do_destroy(struct i915_hw_context *ctx) 134271705Sdumbbell{ 135271705Sdumbbell#if defined(INVARIANTS) 136271705Sdumbbell struct drm_device *dev = ctx->obj->base.dev; 137271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 138271705Sdumbbell#endif 139271705Sdumbbell 140271705Sdumbbell if (ctx->file_priv) 141271705Sdumbbell drm_gem_names_remove(&ctx->file_priv->context_idr, ctx->id); 142271705Sdumbbell else 143271705Sdumbbell KASSERT(ctx == dev_priv->rings[RCS].default_context, 144271705Sdumbbell ("i915_gem_context: ctx != default_context")); 145271705Sdumbbell 146271705Sdumbbell drm_gem_object_unreference(&ctx->obj->base); 147271705Sdumbbell free(ctx, DRM_I915_GEM); 148271705Sdumbbell} 149271705Sdumbbell 150271705Sdumbbellstatic int 151271705Sdumbbellcreate_hw_context(struct drm_device *dev, 152271705Sdumbbell struct drm_i915_file_private *file_priv, 153271705Sdumbbell struct i915_hw_context **ret_ctx) 154271705Sdumbbell{ 155271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 156271705Sdumbbell struct i915_hw_context *ctx; 157271705Sdumbbell int ret, id; 158271705Sdumbbell 159271705Sdumbbell ctx = malloc(sizeof(*ctx), DRM_I915_GEM, M_NOWAIT | M_ZERO); 160271705Sdumbbell if (ctx == NULL) 161271705Sdumbbell return (-ENOMEM); 162271705Sdumbbell 163271705Sdumbbell ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); 164271705Sdumbbell if (ctx->obj == NULL) { 165271705Sdumbbell free(ctx, DRM_I915_GEM); 166271705Sdumbbell DRM_DEBUG_DRIVER("Context object allocated failed\n"); 167271705Sdumbbell return (-ENOMEM); 168271705Sdumbbell } 169271705Sdumbbell 170271705Sdumbbell if (INTEL_INFO(dev)->gen >= 7) { 171271705Sdumbbell ret = i915_gem_object_set_cache_level(ctx->obj, 172271705Sdumbbell I915_CACHE_LLC_MLC); 173271705Sdumbbell if (ret) 174271705Sdumbbell goto err_out; 175271705Sdumbbell } 176271705Sdumbbell 177271705Sdumbbell /* The ring associated with the context object is handled by the normal 178271705Sdumbbell * object tracking code. We give an initial ring value simple to pass an 179271705Sdumbbell * assertion in the context switch code. 180271705Sdumbbell */ 181271705Sdumbbell ctx->ring = &dev_priv->rings[RCS]; 182271705Sdumbbell 183271705Sdumbbell /* Default context will never have a file_priv */ 184271705Sdumbbell if (file_priv == NULL) { 185271705Sdumbbell *ret_ctx = ctx; 186271705Sdumbbell return (0); 187271705Sdumbbell } 188271705Sdumbbell 189271705Sdumbbell ctx->file_priv = file_priv; 190271705Sdumbbell 191271705Sdumbbellagain: 192271705Sdumbbell id = 0; 193271705Sdumbbell ret = drm_gem_name_create(&file_priv->context_idr, ctx, &id); 194271705Sdumbbell if (ret == 0) 195271705Sdumbbell ctx->id = id; 196271705Sdumbbell 197271705Sdumbbell if (ret == -EAGAIN) 198271705Sdumbbell goto again; 199271705Sdumbbell else if (ret) 200271705Sdumbbell goto err_out; 201271705Sdumbbell 202271705Sdumbbell *ret_ctx = ctx; 203271705Sdumbbell return (0); 204271705Sdumbbell 205271705Sdumbbellerr_out: 206271705Sdumbbell do_destroy(ctx); 207271705Sdumbbell return (ret); 208271705Sdumbbell} 209271705Sdumbbell 210271705Sdumbbellstatic inline bool is_default_context(struct i915_hw_context *ctx) 211271705Sdumbbell{ 212271705Sdumbbell return (ctx == ctx->ring->default_context); 213271705Sdumbbell} 214271705Sdumbbell 215271705Sdumbbell/** 216271705Sdumbbell * The default context needs to exist per ring that uses contexts. It stores the 217271705Sdumbbell * context state of the GPU for applications that don't utilize HW contexts, as 218271705Sdumbbell * well as an idle case. 219271705Sdumbbell */ 220271705Sdumbbellstatic int create_default_context(struct drm_i915_private *dev_priv) 221271705Sdumbbell{ 222271705Sdumbbell struct i915_hw_context *ctx; 223271705Sdumbbell int ret; 224271705Sdumbbell 225271705Sdumbbell DRM_LOCK_ASSERT(dev_priv->dev); 226271705Sdumbbell 227271705Sdumbbell ret = create_hw_context(dev_priv->dev, NULL, &ctx); 228271705Sdumbbell if (ret != 0) 229271705Sdumbbell return (ret); 230271705Sdumbbell 231271705Sdumbbell /* We may need to do things with the shrinker which require us to 232271705Sdumbbell * immediately switch back to the default context. This can cause a 233271705Sdumbbell * problem as pinning the default context also requires GTT space which 234271705Sdumbbell * may not be available. To avoid this we always pin the 235271705Sdumbbell * default context. 236271705Sdumbbell */ 237271705Sdumbbell dev_priv->rings[RCS].default_context = ctx; 238271705Sdumbbell ret = i915_gem_object_pin(ctx->obj, CONTEXT_ALIGN, false); 239271705Sdumbbell if (ret) 240271705Sdumbbell goto err_destroy; 241271705Sdumbbell 242271705Sdumbbell ret = do_switch(ctx); 243271705Sdumbbell if (ret) 244271705Sdumbbell goto err_unpin; 245271705Sdumbbell 246271705Sdumbbell DRM_DEBUG_DRIVER("Default HW context loaded\n"); 247271705Sdumbbell return 0; 248271705Sdumbbell 249271705Sdumbbellerr_unpin: 250271705Sdumbbell i915_gem_object_unpin(ctx->obj); 251271705Sdumbbellerr_destroy: 252271705Sdumbbell do_destroy(ctx); 253271705Sdumbbell return ret; 254271705Sdumbbell} 255271705Sdumbbell 256271705Sdumbbellvoid i915_gem_context_init(struct drm_device *dev) 257271705Sdumbbell{ 258271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 259271705Sdumbbell uint32_t ctx_size; 260271705Sdumbbell 261271705Sdumbbell if (!HAS_HW_CONTEXTS(dev)) { 262271705Sdumbbell dev_priv->hw_contexts_disabled = true; 263271705Sdumbbell return; 264271705Sdumbbell } 265271705Sdumbbell 266271705Sdumbbell /* If called from reset, or thaw... we've been here already */ 267271705Sdumbbell if (dev_priv->hw_contexts_disabled || 268271705Sdumbbell dev_priv->rings[RCS].default_context) 269271705Sdumbbell return; 270271705Sdumbbell 271271705Sdumbbell ctx_size = get_context_size(dev); 272271705Sdumbbell dev_priv->hw_context_size = get_context_size(dev); 273271705Sdumbbell dev_priv->hw_context_size = roundup(dev_priv->hw_context_size, 4096); 274271705Sdumbbell 275271705Sdumbbell if (ctx_size <= 0 || ctx_size > (1<<20)) { 276271705Sdumbbell dev_priv->hw_contexts_disabled = true; 277271705Sdumbbell return; 278271705Sdumbbell } 279271705Sdumbbell 280271705Sdumbbell if (create_default_context(dev_priv)) { 281271705Sdumbbell dev_priv->hw_contexts_disabled = true; 282271705Sdumbbell return; 283271705Sdumbbell } 284271705Sdumbbell 285271705Sdumbbell DRM_DEBUG_DRIVER("HW context support initialized\n"); 286271705Sdumbbell} 287271705Sdumbbell 288271705Sdumbbellvoid i915_gem_context_fini(struct drm_device *dev) 289271705Sdumbbell{ 290271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 291271705Sdumbbell 292271705Sdumbbell if (dev_priv->hw_contexts_disabled) 293271705Sdumbbell return; 294271705Sdumbbell 295271705Sdumbbell /* The only known way to stop the gpu from accessing the hw context is 296271705Sdumbbell * to reset it. Do this as the very last operation to avoid confusing 297271705Sdumbbell * other code, leading to spurious errors. */ 298271705Sdumbbell intel_gpu_reset(dev); 299271705Sdumbbell 300271705Sdumbbell i915_gem_object_unpin(dev_priv->rings[RCS].default_context->obj); 301271705Sdumbbell 302271705Sdumbbell do_destroy(dev_priv->rings[RCS].default_context); 303271705Sdumbbell} 304271705Sdumbbell 305271705Sdumbbellstatic int context_idr_cleanup(uint32_t id, void *p, void *data) 306271705Sdumbbell{ 307271705Sdumbbell struct i915_hw_context *ctx = p; 308271705Sdumbbell 309271705Sdumbbell KASSERT(id != DEFAULT_CONTEXT_ID, ("i915_gem_context: id == DEFAULT_CONTEXT_ID in cleanup")); 310271705Sdumbbell 311271705Sdumbbell do_destroy(ctx); 312271705Sdumbbell 313271705Sdumbbell return 0; 314271705Sdumbbell} 315271705Sdumbbell 316271705Sdumbbellvoid i915_gem_context_close(struct drm_device *dev, struct drm_file *file) 317271705Sdumbbell{ 318271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 319271705Sdumbbell 320282199Sdumbbell DRM_LOCK(dev); 321271705Sdumbbell drm_gem_names_foreach(&file_priv->context_idr, context_idr_cleanup, NULL); 322271705Sdumbbell drm_gem_names_fini(&file_priv->context_idr); 323282199Sdumbbell DRM_UNLOCK(dev); 324271705Sdumbbell} 325271705Sdumbbell 326271705Sdumbbellstatic struct i915_hw_context * 327271705Sdumbbelli915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) 328271705Sdumbbell{ 329271705Sdumbbell return (struct i915_hw_context *)drm_gem_find_ptr(&file_priv->context_idr, id); 330271705Sdumbbell} 331271705Sdumbbell 332271705Sdumbbellstatic inline int 333271705Sdumbbellmi_set_context(struct intel_ring_buffer *ring, 334271705Sdumbbell struct i915_hw_context *new_context, 335271705Sdumbbell u32 hw_flags) 336271705Sdumbbell{ 337271705Sdumbbell int ret; 338271705Sdumbbell 339271705Sdumbbell /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB 340271705Sdumbbell * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value 341271705Sdumbbell * explicitly, so we rely on the value at ring init, stored in 342271705Sdumbbell * itlb_before_ctx_switch. 343271705Sdumbbell */ 344271705Sdumbbell if (IS_GEN6(ring->dev) && ring->itlb_before_ctx_switch) { 345271705Sdumbbell ret = ring->flush(ring, I915_GEM_GPU_DOMAINS, 0); 346271705Sdumbbell if (ret) 347271705Sdumbbell return ret; 348271705Sdumbbell } 349271705Sdumbbell 350271705Sdumbbell ret = intel_ring_begin(ring, 6); 351271705Sdumbbell if (ret) 352271705Sdumbbell return ret; 353271705Sdumbbell 354271705Sdumbbell if (IS_GEN7(ring->dev)) 355271705Sdumbbell intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); 356271705Sdumbbell else 357271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 358271705Sdumbbell 359271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 360271705Sdumbbell intel_ring_emit(ring, MI_SET_CONTEXT); 361271705Sdumbbell intel_ring_emit(ring, new_context->obj->gtt_offset | 362271705Sdumbbell MI_MM_SPACE_GTT | 363271705Sdumbbell MI_SAVE_EXT_STATE_EN | 364271705Sdumbbell MI_RESTORE_EXT_STATE_EN | 365271705Sdumbbell hw_flags); 366271705Sdumbbell /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */ 367271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 368271705Sdumbbell 369271705Sdumbbell if (IS_GEN7(ring->dev)) 370271705Sdumbbell intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); 371271705Sdumbbell else 372271705Sdumbbell intel_ring_emit(ring, MI_NOOP); 373271705Sdumbbell 374271705Sdumbbell intel_ring_advance(ring); 375271705Sdumbbell 376271705Sdumbbell return ret; 377271705Sdumbbell} 378271705Sdumbbell 379271705Sdumbbellstatic int do_switch(struct i915_hw_context *to) 380271705Sdumbbell{ 381271705Sdumbbell struct intel_ring_buffer *ring = to->ring; 382271705Sdumbbell struct drm_i915_gem_object *from_obj = ring->last_context_obj; 383271705Sdumbbell u32 hw_flags = 0; 384271705Sdumbbell int ret; 385271705Sdumbbell 386271705Sdumbbell KASSERT(!(from_obj != NULL && from_obj->pin_count == 0), 387271705Sdumbbell ("i915_gem_context: invalid \"from\" context")); 388271705Sdumbbell 389271705Sdumbbell if (from_obj == to->obj) 390271705Sdumbbell return 0; 391271705Sdumbbell 392271705Sdumbbell ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false); 393271705Sdumbbell if (ret) 394271705Sdumbbell return ret; 395271705Sdumbbell 396271705Sdumbbell /* Clear this page out of any CPU caches for coherent swap-in/out. Note 397271705Sdumbbell * that thanks to write = false in this call and us not setting any gpu 398271705Sdumbbell * write domains when putting a context object onto the active list 399271705Sdumbbell * (when switching away from it), this won't block. 400271705Sdumbbell * XXX: We need a real interface to do this instead of trickery. */ 401271705Sdumbbell ret = i915_gem_object_set_to_gtt_domain(to->obj, false); 402271705Sdumbbell if (ret) { 403271705Sdumbbell i915_gem_object_unpin(to->obj); 404271705Sdumbbell return ret; 405271705Sdumbbell } 406271705Sdumbbell 407271705Sdumbbell if (!to->obj->has_global_gtt_mapping) 408280369Skib i915_gem_gtt_bind_object(to->obj, to->obj->cache_level); 409271705Sdumbbell 410271705Sdumbbell if (!to->is_initialized || is_default_context(to)) 411271705Sdumbbell hw_flags |= MI_RESTORE_INHIBIT; 412271705Sdumbbell else if (from_obj == to->obj) /* not yet expected */ 413271705Sdumbbell hw_flags |= MI_FORCE_RESTORE; 414271705Sdumbbell 415271705Sdumbbell ret = mi_set_context(ring, to, hw_flags); 416271705Sdumbbell if (ret) { 417271705Sdumbbell i915_gem_object_unpin(to->obj); 418271705Sdumbbell return ret; 419271705Sdumbbell } 420271705Sdumbbell 421271705Sdumbbell /* The backing object for the context is done after switching to the 422271705Sdumbbell * *next* context. Therefore we cannot retire the previous context until 423271705Sdumbbell * the next context has already started running. In fact, the below code 424271705Sdumbbell * is a bit suboptimal because the retiring can occur simply after the 425271705Sdumbbell * MI_SET_CONTEXT instead of when the next seqno has completed. 426271705Sdumbbell */ 427271705Sdumbbell if (from_obj != NULL) { 428271705Sdumbbell from_obj->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION; 429271705Sdumbbell i915_gem_object_move_to_active(from_obj, ring, 430271705Sdumbbell i915_gem_next_request_seqno(ring)); 431271705Sdumbbell /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the 432271705Sdumbbell * whole damn pipeline, we don't need to explicitly mark the 433271705Sdumbbell * object dirty. The only exception is that the context must be 434271705Sdumbbell * correct in case the object gets swapped out. Ideally we'd be 435271705Sdumbbell * able to defer doing this until we know the object would be 436271705Sdumbbell * swapped, but there is no way to do that yet. 437271705Sdumbbell */ 438271705Sdumbbell from_obj->dirty = 1; 439271705Sdumbbell KASSERT(from_obj->ring == ring, ("i915_gem_context: from_ring != ring")); 440271705Sdumbbell i915_gem_object_unpin(from_obj); 441271705Sdumbbell 442271705Sdumbbell drm_gem_object_unreference(&from_obj->base); 443271705Sdumbbell } 444271705Sdumbbell 445271705Sdumbbell drm_gem_object_reference(&to->obj->base); 446271705Sdumbbell ring->last_context_obj = to->obj; 447271705Sdumbbell to->is_initialized = true; 448271705Sdumbbell 449271705Sdumbbell return 0; 450271705Sdumbbell} 451271705Sdumbbell 452271705Sdumbbell/** 453271705Sdumbbell * i915_switch_context() - perform a GPU context switch. 454271705Sdumbbell * @ring: ring for which we'll execute the context switch 455271705Sdumbbell * @file_priv: file_priv associated with the context, may be NULL 456271705Sdumbbell * @id: context id number 457271705Sdumbbell * @seqno: sequence number by which the new context will be switched to 458271705Sdumbbell * @flags: 459271705Sdumbbell * 460271705Sdumbbell * The context life cycle is simple. The context refcount is incremented and 461271705Sdumbbell * decremented by 1 and create and destroy. If the context is in use by the GPU, 462271705Sdumbbell * it will have a refoucnt > 1. This allows us to destroy the context abstract 463271705Sdumbbell * object while letting the normal object tracking destroy the backing BO. 464271705Sdumbbell */ 465271705Sdumbbellint i915_switch_context(struct intel_ring_buffer *ring, 466271705Sdumbbell struct drm_file *file, 467271705Sdumbbell int to_id) 468271705Sdumbbell{ 469271705Sdumbbell struct drm_i915_private *dev_priv = ring->dev->dev_private; 470271705Sdumbbell struct i915_hw_context *to; 471271705Sdumbbell 472271705Sdumbbell if (dev_priv->hw_contexts_disabled) 473271705Sdumbbell return 0; 474271705Sdumbbell 475271705Sdumbbell if (ring != &dev_priv->rings[RCS]) 476271705Sdumbbell return 0; 477271705Sdumbbell 478271705Sdumbbell if (to_id == DEFAULT_CONTEXT_ID) { 479271705Sdumbbell to = ring->default_context; 480271705Sdumbbell } else { 481271705Sdumbbell if (file == NULL) 482271705Sdumbbell return -EINVAL; 483271705Sdumbbell 484271705Sdumbbell to = i915_gem_context_get(file->driver_priv, to_id); 485271705Sdumbbell if (to == NULL) 486271705Sdumbbell return -ENOENT; 487271705Sdumbbell } 488271705Sdumbbell 489271705Sdumbbell return do_switch(to); 490271705Sdumbbell} 491271705Sdumbbell 492271705Sdumbbellint i915_gem_context_create_ioctl(struct drm_device *dev, void *data, 493271705Sdumbbell struct drm_file *file) 494271705Sdumbbell{ 495271705Sdumbbell struct drm_i915_private *dev_priv = dev->dev_private; 496271705Sdumbbell struct drm_i915_gem_context_create *args = data; 497271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 498271705Sdumbbell struct i915_hw_context *ctx; 499271705Sdumbbell int ret; 500271705Sdumbbell 501271705Sdumbbell if (!(dev->driver->driver_features & DRIVER_GEM)) 502271705Sdumbbell return -ENODEV; 503271705Sdumbbell 504271705Sdumbbell if (dev_priv->hw_contexts_disabled) 505271705Sdumbbell return -ENODEV; 506271705Sdumbbell 507271705Sdumbbell ret = i915_mutex_lock_interruptible(dev); 508271705Sdumbbell if (ret) 509271705Sdumbbell return ret; 510271705Sdumbbell 511271705Sdumbbell ret = create_hw_context(dev, file_priv, &ctx); 512271705Sdumbbell DRM_UNLOCK(dev); 513271705Sdumbbell if (ret != 0) 514271705Sdumbbell return (ret); 515271705Sdumbbell 516271705Sdumbbell args->ctx_id = ctx->id; 517271705Sdumbbell DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id); 518271705Sdumbbell 519271705Sdumbbell return 0; 520271705Sdumbbell} 521271705Sdumbbell 522271705Sdumbbellint i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data, 523271705Sdumbbell struct drm_file *file) 524271705Sdumbbell{ 525271705Sdumbbell struct drm_i915_gem_context_destroy *args = data; 526271705Sdumbbell struct drm_i915_file_private *file_priv = file->driver_priv; 527271705Sdumbbell struct i915_hw_context *ctx; 528271705Sdumbbell int ret; 529271705Sdumbbell 530271705Sdumbbell if (!(dev->driver->driver_features & DRIVER_GEM)) 531271705Sdumbbell return -ENODEV; 532271705Sdumbbell 533271705Sdumbbell ret = i915_mutex_lock_interruptible(dev); 534271705Sdumbbell if (ret) 535271705Sdumbbell return ret; 536271705Sdumbbell 537271705Sdumbbell ctx = i915_gem_context_get(file_priv, args->ctx_id); 538271705Sdumbbell if (!ctx) { 539271705Sdumbbell DRM_UNLOCK(dev); 540271705Sdumbbell return -ENOENT; 541271705Sdumbbell } 542271705Sdumbbell 543271705Sdumbbell do_destroy(ctx); 544271705Sdumbbell 545271705Sdumbbell DRM_UNLOCK(dev); 546271705Sdumbbell 547271705Sdumbbell DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id); 548271705Sdumbbell return 0; 549271705Sdumbbell} 550