Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6095868a authored by Chris Wilson's avatar Chris Wilson
Browse files

drm/i915: Complete kerneldoc for struct i915_gem_context



The existing kerneldoc was outdated, so time for a refresh.

v2: Use single line kdoc, mention functions for manipulation

Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/20161231112012.29263-3-chris@chris-wilson.co.uk
parent a73c7a44
Loading
Loading
Loading
Loading
+1 −98
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#include "intel_ringbuffer.h"

#include "i915_gem.h"
#include "i915_gem_context.h"
#include "i915_gem_fence_reg.h"
#include "i915_gem_object.h"
#include "i915_gem_gtt.h"
@@ -1048,76 +1049,6 @@ enum i915_cache_level {

#define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */

#define DEFAULT_CONTEXT_HANDLE 0

/**
 * struct i915_gem_context - as the name implies, represents a context.
 * @ref: reference count.
 * @user_handle: userspace tracking identity for this context.
 * @remap_slice: l3 row remapping information.
 * @flags: context specific flags:
 *         CONTEXT_NO_ZEROMAP: do not allow mapping things to page 0.
 * @file_priv: filp associated with this context (NULL for global default
 *	       context).
 * @hang_stats: information about the role of this context in possible GPU
 *		hangs.
 * @ppgtt: virtual memory space used by this context.
 * @legacy_hw_ctx: render context backing object and whether it is correctly
 *                initialized (legacy ring submission mechanism only).
 * @link: link in the global list of contexts.
 *
 * Contexts are memory images used by the hardware to store copies of their
 * internal state.
 */
struct i915_gem_context {
	struct kref ref;
	struct drm_i915_private *i915;
	struct drm_i915_file_private *file_priv;
	struct i915_hw_ppgtt *ppgtt;
	struct pid *pid;
	const char *name;

	unsigned long flags;
#define CONTEXT_NO_ZEROMAP		BIT(0)
#define CONTEXT_NO_ERROR_CAPTURE	BIT(1)

	/* Unique identifier for this context, used by the hw for tracking */
	unsigned int hw_id;
	u32 user_handle;
	int priority; /* greater priorities are serviced first */

	u32 ggtt_alignment;
	u32 ggtt_offset_bias;

	struct intel_context {
		struct i915_vma *state;
		struct intel_ring *ring;
		uint32_t *lrc_reg_state;
		u64 lrc_desc;
		int pin_count;
		bool initialised;
	} engine[I915_NUM_ENGINES];
	u32 ring_size;
	u32 desc_template;
	struct atomic_notifier_head status_notifier;
	bool execlists_force_single_submission;

	struct list_head link;

	u8 remap_slice;
	bool closed:1;
	bool bannable:1;
	bool banned:1;

	unsigned int guilty_count; /* guilty of a hang */
	unsigned int active_count; /* active during hang */

#define CONTEXT_SCORE_GUILTY		10
#define CONTEXT_SCORE_BAN_THRESHOLD	40
	/* Accumulated score of hangs caused by this context */
	int ban_score;
};

enum fb_op_origin {
	ORIGIN_GTT,
	ORIGIN_CPU,
@@ -3494,18 +3425,6 @@ void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj,
void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
					 struct sg_table *pages);

/* i915_gem_context.c */
int __must_check i915_gem_context_init(struct drm_i915_private *dev_priv);
void i915_gem_context_lost(struct drm_i915_private *dev_priv);
void i915_gem_context_fini(struct drm_i915_private *dev_priv);
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct drm_i915_gem_request *req);
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
void i915_gem_context_free(struct kref *ctx_ref);
struct i915_gem_context *
i915_gem_context_create_gvt(struct drm_device *dev);

static inline struct i915_gem_context *
i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{
@@ -3551,22 +3470,6 @@ i915_gem_context_lookup_timeline(struct i915_gem_context *ctx,
	return &vm->timeline.engine[engine->id];
}

static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
{
	return c->user_handle == DEFAULT_CONTEXT_HANDLE;
}

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
				  struct drm_file *file);
int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file);
int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv);
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv);
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
				       struct drm_file *file);

int i915_perf_open_ioctl(struct drm_device *dev, void *data,
			 struct drm_file *file);

+8 −18
Original line number Diff line number Diff line
@@ -2657,34 +2657,24 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
	goto out_unlock;
}

static bool i915_context_is_banned(const struct i915_gem_context *ctx)
static bool ban_context(const struct i915_gem_context *ctx)
{
	if (ctx->banned)
		return true;

	if (!ctx->bannable)
		return false;

	if (ctx->ban_score >= CONTEXT_SCORE_BAN_THRESHOLD) {
		DRM_DEBUG("context hanging too often, banning!\n");
		return true;
	}

	return false;
	return (i915_gem_context_is_bannable(ctx) &&
		ctx->ban_score >= CONTEXT_SCORE_BAN_THRESHOLD);
}

static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{
	ctx->ban_score += CONTEXT_SCORE_GUILTY;

	ctx->banned = i915_context_is_banned(ctx);
	ctx->guilty_count++;
	ctx->ban_score += CONTEXT_SCORE_GUILTY;
	if (ban_context(ctx))
		i915_gem_context_set_banned(ctx);

	DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
			 ctx->name, ctx->ban_score,
			 yesno(ctx->banned));
			 yesno(i915_gem_context_is_banned(ctx)));

	if (!ctx->banned || IS_ERR_OR_NULL(ctx->file_priv))
	if (!i915_gem_context_is_banned(ctx) || IS_ERR_OR_NULL(ctx->file_priv))
		return;

	ctx->file_priv->context_bans++;
+17 −16
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ void i915_gem_context_free(struct kref *ctx_ref)

	lockdep_assert_held(&ctx->i915->drm.struct_mutex);
	trace_i915_context_free(ctx);
	GEM_BUG_ON(!ctx->closed);
	GEM_BUG_ON(!i915_gem_context_is_closed(ctx));

	i915_ppgtt_put(ctx->ppgtt);

@@ -228,8 +228,7 @@ static void i915_ppgtt_close(struct i915_address_space *vm)

static void context_close(struct i915_gem_context *ctx)
{
	GEM_BUG_ON(ctx->closed);
	ctx->closed = true;
	i915_gem_context_set_closed(ctx);
	if (ctx->ppgtt)
		i915_ppgtt_close(&ctx->ppgtt->base);
	ctx->file_priv = ERR_PTR(-EBADF);
@@ -329,7 +328,7 @@ __create_hw_context(struct drm_i915_private *dev_priv,
	 * is no remap info, it will be a NOP. */
	ctx->remap_slice = ALL_L3_SLICES(dev_priv);

	ctx->bannable = true;
	i915_gem_context_set_bannable(ctx);
	ctx->ring_size = 4 * PAGE_SIZE;
	ctx->desc_template = GEN8_CTX_ADDRESSING_MODE(dev_priv) <<
			     GEN8_CTX_ADDRESSING_MODE_SHIFT;
@@ -418,8 +417,9 @@ i915_gem_context_create_gvt(struct drm_device *dev)
	if (IS_ERR(ctx))
		goto out;

	ctx->closed = true; /* not user accessible */
	ctx->execlists_force_single_submission = true;
	i915_gem_context_set_closed(ctx); /* not user accessible */
	i915_gem_context_clear_bannable(ctx);
	i915_gem_context_set_force_single_submission(ctx);
	ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */
out:
	mutex_unlock(&dev->struct_mutex);
@@ -468,6 +468,7 @@ int i915_gem_context_init(struct drm_i915_private *dev_priv)
		return PTR_ERR(ctx);
	}

	i915_gem_context_clear_bannable(ctx);
	ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
	dev_priv->kernel_context = ctx;

@@ -1040,10 +1041,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
			args->value = to_i915(dev)->ggtt.base.total;
		break;
	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
		args->value = !!(ctx->flags & CONTEXT_NO_ERROR_CAPTURE);
		args->value = i915_gem_context_no_error_capture(ctx);
		break;
	case I915_CONTEXT_PARAM_BANNABLE:
		args->value = ctx->bannable;
		args->value = i915_gem_context_is_bannable(ctx);
		break;
	default:
		ret = -EINVAL;
@@ -1085,22 +1086,22 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
		}
		break;
	case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE:
		if (args->size) {
		if (args->size)
			ret = -EINVAL;
		} else {
			if (args->value)
				ctx->flags |= CONTEXT_NO_ERROR_CAPTURE;
		else if (args->value)
			i915_gem_context_set_no_error_capture(ctx);
		else
				ctx->flags &= ~CONTEXT_NO_ERROR_CAPTURE;
		}
			i915_gem_context_clear_no_error_capture(ctx);
		break;
	case I915_CONTEXT_PARAM_BANNABLE:
		if (args->size)
			ret = -EINVAL;
		else if (!capable(CAP_SYS_ADMIN) && !args->value)
			ret = -EPERM;
		else if (args->value)
			i915_gem_context_set_bannable(ctx);
		else
			ctx->bannable = args->value;
			i915_gem_context_clear_bannable(ctx);
		break;
	default:
		ret = -EINVAL;
+272 −0
Original line number Diff line number Diff line
/*
 * Copyright © 2016 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 *
 */

#ifndef __I915_GEM_CONTEXT_H__
#define __I915_GEM_CONTEXT_H__

#include <linux/bitops.h>
#include <linux/list.h>

struct pid;

struct drm_device;
struct drm_file;

struct drm_i915_private;
struct drm_i915_file_private;
struct i915_hw_ppgtt;
struct i915_vma;
struct intel_ring;

#define DEFAULT_CONTEXT_HANDLE 0

/**
 * 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 {
	/** i915: i915 device backpointer */
	struct drm_i915_private *i915;

	/** file_priv: owning file descriptor */
	struct drm_i915_file_private *file_priv;

	/**
	 * @ppgtt: unique address space (GTT)
	 *
	 * In full-ppgtt mode, each context has its own address space ensuring
	 * complete seperation of one client from all others.
	 *
	 * In other modes, this is a NULL pointer with the expectation that
	 * the caller uses the shared global GTT.
	 */
	struct i915_hw_ppgtt *ppgtt;

	/**
	 * @pid: process id of creator
	 *
	 * Note that who created the context may not be the principle user,
	 * as the context may be shared across a local socket. However,
	 * that should only affect the default context, all contexts created
	 * explicitly by the client are expected to be isolated.
	 */
	struct pid *pid;

	/**
	 * @name: arbitrary name
	 *
	 * A name is constructed for the context from the creator's process
	 * name, pid and user handle in order to uniquely identify the
	 * context in messages.
	 */
	const char *name;

	/** link: place with &drm_i915_private.context_list */
	struct list_head link;

	/**
	 * @ref: reference count
	 *
	 * A reference to a context is held by both the client who created it
	 * and on each request submitted to the hardware using the request
	 * (to ensure the hardware has access to the state until it has
	 * finished all pending writes). See i915_gem_context_get() and
	 * i915_gem_context_put() for access.
	 */
	struct kref ref;

	/**
	 * @flags: small set of booleans
	 */
	unsigned long flags;
#define CONTEXT_NO_ZEROMAP		BIT(0)
#define CONTEXT_NO_ERROR_CAPTURE	1
#define CONTEXT_CLOSED			2
#define CONTEXT_BANNABLE		3
#define CONTEXT_BANNED			4
#define CONTEXT_FORCE_SINGLE_SUBMISSION	5

	/**
	 * @hw_id: - unique identifier for the context
	 *
	 * The hardware needs to uniquely identify the context for a few
	 * functions like fault reporting, PASID, scheduling. The
	 * &drm_i915_private.context_hw_ida is used to assign a unqiue
	 * id for the lifetime of the context.
	 */
	unsigned int hw_id;

	/**
	 * @user_handle: userspace identifier
	 *
	 * A unique per-file identifier is generated from
	 * &drm_i915_file_private.contexts.
	 */
	u32 user_handle;

	/**
	 * @priority: execution and service priority
	 *
	 * All clients are equal, but some are more equal than others!
	 *
	 * Requests from a context with a greater (more positive) value of
	 * @priority will be executed before those with a lower @priority
	 * value, forming a simple QoS.
	 *
	 * The &drm_i915_private.kernel_context is assigned the lowest priority.
	 */
	int priority;

	/** ggtt_alignment: alignment restriction for context objects */
	u32 ggtt_alignment;
	/** ggtt_offset_bias: placement restriction for context objects */
	u32 ggtt_offset_bias;

	/** engine: per-engine logical HW state */
	struct intel_context {
		struct i915_vma *state;
		struct intel_ring *ring;
		u32 *lrc_reg_state;
		u64 lrc_desc;
		int pin_count;
		bool initialised;
	} engine[I915_NUM_ENGINES];

	/** ring_size: size for allocating the per-engine ring buffer */
	u32 ring_size;
	/** desc_template: invariant fields for the HW context descriptor */
	u32 desc_template;

	/** status_notifier: list of callbacks for context-switch changes */
	struct atomic_notifier_head status_notifier;

	/** guilty_count: How many times this context has caused a GPU hang. */
	unsigned int guilty_count;
	/**
	 * @active_count: How many times this context was active during a GPU
	 * hang, but did not cause it.
	 */
	unsigned int active_count;

#define CONTEXT_SCORE_GUILTY		10
#define CONTEXT_SCORE_BAN_THRESHOLD	40
	/** ban_score: Accumulated score of all hangs caused by this context. */
	int ban_score;

	/** remap_slice: Bitmask of cache lines that need remapping */
	u8 remap_slice;
};

static inline bool i915_gem_context_is_closed(const struct i915_gem_context *ctx)
{
	return test_bit(CONTEXT_CLOSED, &ctx->flags);
}

static inline void i915_gem_context_set_closed(struct i915_gem_context *ctx)
{
	GEM_BUG_ON(i915_gem_context_is_closed(ctx));
	__set_bit(CONTEXT_CLOSED, &ctx->flags);
}

static inline bool i915_gem_context_no_error_capture(const struct i915_gem_context *ctx)
{
	return test_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags);
}

static inline void i915_gem_context_set_no_error_capture(struct i915_gem_context *ctx)
{
	__set_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags);
}

static inline void i915_gem_context_clear_no_error_capture(struct i915_gem_context *ctx)
{
	__clear_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags);
}

static inline bool i915_gem_context_is_bannable(const struct i915_gem_context *ctx)
{
	return test_bit(CONTEXT_BANNABLE, &ctx->flags);
}

static inline void i915_gem_context_set_bannable(struct i915_gem_context *ctx)
{
	__set_bit(CONTEXT_BANNABLE, &ctx->flags);
}

static inline void i915_gem_context_clear_bannable(struct i915_gem_context *ctx)
{
	__clear_bit(CONTEXT_BANNABLE, &ctx->flags);
}

static inline bool i915_gem_context_is_banned(const struct i915_gem_context *ctx)
{
	return test_bit(CONTEXT_BANNED, &ctx->flags);
}

static inline void i915_gem_context_set_banned(struct i915_gem_context *ctx)
{
	__set_bit(CONTEXT_BANNED, &ctx->flags);
}

static inline bool i915_gem_context_force_single_submission(const struct i915_gem_context *ctx)
{
	return test_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ctx->flags);
}

static inline void i915_gem_context_set_force_single_submission(struct i915_gem_context *ctx)
{
	__set_bit(CONTEXT_FORCE_SINGLE_SUBMISSION, &ctx->flags);
}

static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
{
	return c->user_handle == DEFAULT_CONTEXT_HANDLE;
}

/* i915_gem_context.c */
int __must_check i915_gem_context_init(struct drm_i915_private *dev_priv);
void i915_gem_context_lost(struct drm_i915_private *dev_priv);
void i915_gem_context_fini(struct drm_i915_private *dev_priv);
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct drm_i915_gem_request *req);
int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv);
void i915_gem_context_free(struct kref *ctx_ref);
struct i915_gem_context *
i915_gem_context_create_gvt(struct drm_device *dev);

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
				  struct drm_file *file);
int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file);
int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv);
int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
				    struct drm_file *file_priv);
int i915_gem_context_reset_stats_ioctl(struct drm_device *dev, void *data,
				       struct drm_file *file);

#endif /* !__I915_GEM_CONTEXT_H__ */
+1 −1
Original line number Diff line number Diff line
@@ -1238,7 +1238,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
	if (IS_ERR(ctx))
		return ctx;

	if (ctx->banned) {
	if (i915_gem_context_is_banned(ctx)) {
		DRM_DEBUG("Context %u tried to submit while banned\n", ctx_id);
		return ERR_PTR(-EIO);
	}
Loading