Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 * Copyright © 2014-2017 Intel Corporation
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice (including the next
 12 * paragraph) shall be included in all copies or substantial portions of the
 13 * Software.
 14 *
 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21 * IN THE SOFTWARE.
 22 *
 23 */
 24
 25#include "intel_guc_ads.h"
 26#include "intel_uc.h"
 27#include "i915_drv.h"
 28
 29/*
 30 * The Additional Data Struct (ADS) has pointers for different buffers used by
 31 * the GuC. One single gem object contains the ADS struct itself (guc_ads), the
 32 * scheduling policies (guc_policies), a structure describing a collection of
 33 * register sets (guc_mmio_reg_state) and some extra pages for the GuC to save
 34 * its internal state for sleep.
 35 */
 36
 37static void guc_policy_init(struct guc_policy *policy)
 38{
 39	policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US;
 40	policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US;
 41	policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US;
 42	policy->policy_flags = 0;
 43}
 44
 45static void guc_policies_init(struct guc_policies *policies)
 46{
 47	struct guc_policy *policy;
 48	u32 p, i;
 49
 50	policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US;
 51	policies->max_num_work_items = POLICY_MAX_NUM_WI;
 52
 53	for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) {
 54		for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) {
 55			policy = &policies->policy[p][i];
 56
 57			guc_policy_init(policy);
 58		}
 59	}
 60
 61	policies->is_valid = 1;
 62}
 63
 64/*
 65 * The first 80 dwords of the register state context, containing the
 66 * execlists and ppgtt registers.
 67 */
 68#define LR_HW_CONTEXT_SIZE	(80 * sizeof(u32))
 69
 70/**
 71 * intel_guc_ads_create() - creates GuC ADS
 72 * @guc: intel_guc struct
 73 *
 74 */
 75int intel_guc_ads_create(struct intel_guc *guc)
 76{
 77	struct drm_i915_private *dev_priv = guc_to_i915(guc);
 78	struct i915_vma *vma;
 79	struct page *page;
 80	/* The ads obj includes the struct itself and buffers passed to GuC */
 81	struct {
 82		struct guc_ads ads;
 83		struct guc_policies policies;
 84		struct guc_mmio_reg_state reg_state;
 85		u8 reg_state_buffer[GUC_S3_SAVE_SPACE_PAGES * PAGE_SIZE];
 86	} __packed *blob;
 87	struct intel_engine_cs *engine;
 88	enum intel_engine_id id;
 89	const u32 skipped_offset = LRC_HEADER_PAGES * PAGE_SIZE;
 90	const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE;
 91	u32 base;
 92
 93	GEM_BUG_ON(guc->ads_vma);
 94
 95	vma = intel_guc_allocate_vma(guc, PAGE_ALIGN(sizeof(*blob)));
 96	if (IS_ERR(vma))
 97		return PTR_ERR(vma);
 98
 99	guc->ads_vma = vma;
100
101	page = i915_vma_first_page(vma);
102	blob = kmap(page);
103
104	/* GuC scheduling policies */
105	guc_policies_init(&blob->policies);
106
107	/* MMIO reg state */
108	for_each_engine(engine, dev_priv, id) {
109		blob->reg_state.white_list[engine->guc_id].mmio_start =
110			engine->mmio_base + GUC_MMIO_WHITE_LIST_START;
111
112		/* Nothing to be saved or restored for now. */
113		blob->reg_state.white_list[engine->guc_id].count = 0;
114	}
115
116	/*
117	 * The GuC requires a "Golden Context" when it reinitialises
118	 * engines after a reset. Here we use the Render ring default
119	 * context, which must already exist and be pinned in the GGTT,
120	 * so its address won't change after we've told the GuC where
121	 * to find it. Note that we have to skip our header (1 page),
122	 * because our GuC shared data is there.
123	 */
124	blob->ads.golden_context_lrca =
125		guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) +
126		skipped_offset;
127
128	/*
129	 * The GuC expects us to exclude the portion of the context image that
130	 * it skips from the size it is to read. It starts reading from after
131	 * the execlist context (so skipping the first page [PPHWSP] and 80
132	 * dwords). Weird guc is weird.
133	 */
134	for_each_engine(engine, dev_priv, id)
135		blob->ads.eng_state_size[engine->guc_id] =
136			engine->context_size - skipped_size;
137
138	base = guc_ggtt_offset(vma);
139	blob->ads.scheduler_policies = base + ptr_offset(blob, policies);
140	blob->ads.reg_state_buffer = base + ptr_offset(blob, reg_state_buffer);
141	blob->ads.reg_state_addr = base + ptr_offset(blob, reg_state);
142
143	kunmap(page);
144
145	return 0;
146}
147
148void intel_guc_ads_destroy(struct intel_guc *guc)
149{
150	i915_vma_unpin_and_release(&guc->ads_vma);
151}