linux/drivers/gpu/drm/i915/gem/i915_gem_context_types.h

/*
 * SPDX-License-Identifier: MIT
 *
 * Copyright © 2019 Intel Corporation
 */

#ifndef __I915_GEM_CONTEXT_TYPES_H__
#define __I915_GEM_CONTEXT_TYPES_H__

#include <linux/atomic.h>
#include <linux/list.h>
#include <linux/llist.h>
#include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/radix-tree.h>
#include <linux/rbtree.h>
#include <linux/rcupdate.h>
#include <linux/types.h>

#include "gt/intel_context_types.h"

#include "i915_scheduler.h"
#include "i915_sw_fence.h"

struct pid;

struct drm_i915_private;
struct drm_i915_file_private;
struct i915_address_space;
struct intel_timeline;
struct intel_ring;

/**
 * struct i915_gem_engines - A set of engines
 */
struct i915_gem_engines {};

/**
 * struct i915_gem_engines_iter - Iterator for an i915_gem_engines set
 */
struct i915_gem_engines_iter {};

/**
 * enum i915_gem_engine_type - Describes the type of an i915_gem_proto_engine
 */
enum i915_gem_engine_type {};

/**
 * struct i915_gem_proto_engine - prototype engine
 *
 * This struct describes an engine that a context may contain.  Engines
 * have four types:
 *
 *  - I915_GEM_ENGINE_TYPE_INVALID: Invalid engines can be created but they
 *    show up as a NULL in i915_gem_engines::engines[i] and any attempt to
 *    use them by the user results in -EINVAL.  They are also useful during
 *    proto-context construction because the client may create invalid
 *    engines and then set them up later as virtual engines.
 *
 *  - I915_GEM_ENGINE_TYPE_PHYSICAL: A single physical engine, described by
 *    i915_gem_proto_engine::engine.
 *
 *  - I915_GEM_ENGINE_TYPE_BALANCED: A load-balanced engine set, described
 *    i915_gem_proto_engine::num_siblings and i915_gem_proto_engine::siblings.
 *
 *  - I915_GEM_ENGINE_TYPE_PARALLEL: A parallel submission engine set, described
 *    i915_gem_proto_engine::width, i915_gem_proto_engine::num_siblings, and
 *    i915_gem_proto_engine::siblings.
 */
struct i915_gem_proto_engine {};

/**
 * struct i915_gem_proto_context - prototype context
 *
 * The struct i915_gem_proto_context represents the creation parameters for
 * a struct i915_gem_context.  This is used to gather parameters provided
 * either through creation flags or via SET_CONTEXT_PARAM so that, when we
 * create the final i915_gem_context, those parameters can be immutable.
 *
 * The context uAPI allows for two methods of setting context parameters:
 * SET_CONTEXT_PARAM and CONTEXT_CREATE_EXT_SETPARAM.  The former is
 * allowed to be called at any time while the later happens as part of
 * GEM_CONTEXT_CREATE.  When these were initially added, Currently,
 * everything settable via one is settable via the other.  While some
 * params are fairly simple and setting them on a live context is harmless
 * such the context priority, others are far trickier such as the VM or the
 * set of engines.  To avoid some truly nasty race conditions, we don't
 * allow setting the VM or the set of engines on live contexts.
 *
 * The way we dealt with this without breaking older userspace that sets
 * the VM or engine set via SET_CONTEXT_PARAM is to delay the creation of
 * the actual context until after the client is done configuring it with
 * SET_CONTEXT_PARAM.  From the perspective of the client, it has the same
 * u32 context ID the whole time.  From the perspective of i915, however,
 * it's an i915_gem_proto_context right up until the point where we attempt
 * to do something which the proto-context can't handle at which point the
 * real context gets created.
 *
 * This is accomplished via a little xarray dance.  When GEM_CONTEXT_CREATE
 * is called, we create a proto-context, reserve a slot in context_xa but
 * leave it NULL, the proto-context in the corresponding slot in
 * proto_context_xa.  Then, whenever we go to look up a context, we first
 * check context_xa.  If it's there, we return the i915_gem_context and
 * we're done.  If it's not, we look in proto_context_xa and, if we find it
 * there, we create the actual context and kill the proto-context.
 *
 * At the time we made this change (April, 2021), we did a fairly complete
 * audit of existing userspace to ensure this wouldn't break anything:
 *
 *  - Mesa/i965 didn't use the engines or VM APIs at all
 *
 *  - Mesa/ANV used the engines API but via CONTEXT_CREATE_EXT_SETPARAM and
 *    didn't use the VM API.
 *
 *  - Mesa/iris didn't use the engines or VM APIs at all
 *
 *  - The open-source compute-runtime didn't yet use the engines API but
 *    did use the VM API via SET_CONTEXT_PARAM.  However, CONTEXT_SETPARAM
 *    was always the second ioctl on that context, immediately following
 *    GEM_CONTEXT_CREATE.
 *
 *  - The media driver sets engines and bonding/balancing via
 *    SET_CONTEXT_PARAM.  However, CONTEXT_SETPARAM to set the VM was
 *    always the second ioctl on that context, immediately following
 *    GEM_CONTEXT_CREATE and setting engines immediately followed that.
 *
 * In order for this dance to work properly, any modification to an
 * i915_gem_proto_context that is exposed to the client via
 * drm_i915_file_private::proto_context_xa must be guarded by
 * drm_i915_file_private::proto_context_lock.  The exception is when a
 * proto-context has not yet been exposed such as when handling
 * CONTEXT_CREATE_SET_PARAM during GEM_CONTEXT_CREATE.
 */
struct i915_gem_proto_context {};

/**
 * struct i915_gem_context - client state
 *
 * The struct i915_gem_context represents the combined view of the driver and
 * logical hardware state for a particular client.
 */
struct i915_gem_context {};

#endif /* __I915_GEM_CONTEXT_TYPES_H__ */