brintos

brintos / linux-shallow public Read only

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