File Index
Files and directories
Sign in
FILE

intel_guc_hwconfig.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2022 Intel Corporation
  4 */
  5
  6#include "gt/intel_gt.h"
  7#include "gt/intel_hwconfig.h"
  8#include "i915_drv.h"
  9#include "i915_memcpy.h"
 10#include "intel_guc_print.h"
 11
 12/*
 13 * GuC has a blob containing hardware configuration information (HWConfig).
 14 * This is formatted as a simple and flexible KLV (Key/Length/Value) table.
 15 *
 16 * For example, a minimal version could be:
 17 *   enum device_attr {
 18 *     ATTR_SOME_VALUE = 0,
 19 *     ATTR_SOME_MASK  = 1,
 20 *   };
 21 *
 22 *   static const u32 hwconfig[] = {
 23 *     ATTR_SOME_VALUE,
 24 *     1,		// Value Length in DWords
 25 *     8,		// Value
 26 *
 27 *     ATTR_SOME_MASK,
 28 *     3,
 29 *     0x00FFFFFFFF, 0xFFFFFFFF, 0xFF000000,
 30 *   };
 31 *
 32 * The attribute ids are defined in a hardware spec.
 33 */
 34
 35static int __guc_action_get_hwconfig(struct intel_guc *guc,
 36				     u32 ggtt_offset, u32 ggtt_size)
 37{
 38	u32 action[] = {
 39		INTEL_GUC_ACTION_GET_HWCONFIG,
 40		lower_32_bits(ggtt_offset),
 41		upper_32_bits(ggtt_offset),
 42		ggtt_size,
 43	};
 44	int ret;
 45
 46	guc_dbg(guc, "Querying HW config table: size = %d, offset = 0x%08X\n",
 47		ggtt_size, ggtt_offset);
 48	ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0);
 49	if (ret == -ENXIO)
 50		return -ENOENT;
 51
 52	return ret;
 53}
 54
 55static int guc_hwconfig_discover_size(struct intel_guc *guc, struct intel_hwconfig *hwconfig)
 56{
 57	int ret;
 58
 59	/*
 60	 * Sending a query with zero offset and size will return the
 61	 * size of the blob.
 62	 */
 63	ret = __guc_action_get_hwconfig(guc, 0, 0);
 64	if (ret < 0)
 65		return ret;
 66
 67	if (ret == 0)
 68		return -EINVAL;
 69
 70	hwconfig->size = ret;
 71	return 0;
 72}
 73
 74static int guc_hwconfig_fill_buffer(struct intel_guc *guc, struct intel_hwconfig *hwconfig)
 75{
 76	struct i915_vma *vma;
 77	u32 ggtt_offset;
 78	void *vaddr;
 79	int ret;
 80
 81	GEM_BUG_ON(!hwconfig->size);
 82
 83	ret = intel_guc_allocate_and_map_vma(guc, hwconfig->size, &vma, &vaddr);
 84	if (ret)
 85		return ret;
 86
 87	ggtt_offset = intel_guc_ggtt_offset(guc, vma);
 88
 89	ret = __guc_action_get_hwconfig(guc, ggtt_offset, hwconfig->size);
 90	if (ret >= 0)
 91		memcpy(hwconfig->ptr, vaddr, hwconfig->size);
 92
 93	i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP);
 94
 95	return ret;
 96}
 97
 98static bool has_table(struct drm_i915_private *i915)
 99{
100	if (IS_ALDERLAKE_P(i915) && !IS_ALDERLAKE_P_N(i915))
101		return true;
102	if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55))
103		return true;
104
105	return false;
106}
107
108/*
109 * intel_guc_hwconfig_init - Initialize the HWConfig
110 *
111 * Retrieve the HWConfig table from the GuC and save it locally.
112 * It can then be queried on demand by other users later on.
113 */
114static int guc_hwconfig_init(struct intel_gt *gt)
115{
116	struct intel_hwconfig *hwconfig = &gt->info.hwconfig;
117	struct intel_guc *guc = gt_to_guc(gt);
118	int ret;
119
120	if (!has_table(gt->i915))
121		return 0;
122
123	ret = guc_hwconfig_discover_size(guc, hwconfig);
124	if (ret)
125		return ret;
126
127	hwconfig->ptr = kmalloc(hwconfig->size, GFP_KERNEL);
128	if (!hwconfig->ptr) {
129		hwconfig->size = 0;
130		return -ENOMEM;
131	}
132
133	ret = guc_hwconfig_fill_buffer(guc, hwconfig);
134	if (ret < 0) {
135		intel_gt_fini_hwconfig(gt);
136		return ret;
137	}
138
139	return 0;
140}
141
142/*
143 * intel_gt_init_hwconfig - Initialize the HWConfig if available
144 *
145 * Retrieve the HWConfig table if available on the current platform.
146 */
147int intel_gt_init_hwconfig(struct intel_gt *gt)
148{
149	if (!intel_uc_uses_guc(&gt->uc))
150		return 0;
151
152	return guc_hwconfig_init(gt);
153}
154
155/*
156 * intel_gt_fini_hwconfig - Finalize the HWConfig
157 *
158 * Free up the memory allocation holding the table.
159 */
160void intel_gt_fini_hwconfig(struct intel_gt *gt)
161{
162	struct intel_hwconfig *hwconfig = &gt->info.hwconfig;
163
164	kfree(hwconfig->ptr);
165	hwconfig->size = 0;
166	hwconfig->ptr = NULL;
167}
~/ Read-only file preview.