brintos

brintos / linux-shallow public Read only

0
0
Text · 11.0 KiB · fae5be5 Raw
419 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023-2024 Intel Corporation4 */5 6#include "abi/guc_actions_sriov_abi.h"7 8#include "xe_bo.h"9#include "xe_gt.h"10#include "xe_gt_sriov_pf_helpers.h"11#include "xe_gt_sriov_pf_policy.h"12#include "xe_gt_sriov_printk.h"13#include "xe_guc_ct.h"14#include "xe_guc_klv_helpers.h"15#include "xe_pm.h"16 17/*18 * Return: number of KLVs that were successfully parsed and saved,19 *         negative error code on failure.20 */21static int guc_action_update_vgt_policy(struct xe_guc *guc, u64 addr, u32 size)22{23	u32 request[] = {24		GUC_ACTION_PF2GUC_UPDATE_VGT_POLICY,25		lower_32_bits(addr),26		upper_32_bits(addr),27		size,28	};29 30	return xe_guc_ct_send_block(&guc->ct, request, ARRAY_SIZE(request));31}32 33/*34 * Return: number of KLVs that were successfully parsed and saved,35 *         negative error code on failure.36 */37static int pf_send_policy_klvs(struct xe_gt *gt, const u32 *klvs, u32 num_dwords)38{39	const u32 bytes = num_dwords * sizeof(u32);40	struct xe_tile *tile = gt_to_tile(gt);41	struct xe_device *xe = tile_to_xe(tile);42	struct xe_guc *guc = &gt->uc.guc;43	struct xe_bo *bo;44	int ret;45 46	bo = xe_bo_create_pin_map(xe, tile, NULL,47				  ALIGN(bytes, PAGE_SIZE),48				  ttm_bo_type_kernel,49				  XE_BO_FLAG_VRAM_IF_DGFX(tile) |50				  XE_BO_FLAG_GGTT);51	if (IS_ERR(bo))52		return PTR_ERR(bo);53 54	xe_map_memcpy_to(xe, &bo->vmap, 0, klvs, bytes);55 56	ret = guc_action_update_vgt_policy(guc, xe_bo_ggtt_addr(bo), num_dwords);57 58	xe_bo_unpin_map_no_vm(bo);59 60	return ret;61}62 63/*64 * Return: 0 on success, -ENOKEY if some KLVs were not updated, -EPROTO if reply was malformed,65 *         negative error code on failure.66 */67static int pf_push_policy_klvs(struct xe_gt *gt, u32 num_klvs,68			       const u32 *klvs, u32 num_dwords)69{70	int ret;71 72	xe_gt_assert(gt, num_klvs == xe_guc_klv_count(klvs, num_dwords));73 74	ret = pf_send_policy_klvs(gt, klvs, num_dwords);75 76	if (ret != num_klvs) {77		int err = ret < 0 ? ret : ret < num_klvs ? -ENOKEY : -EPROTO;78		struct drm_printer p = xe_gt_info_printer(gt);79 80		xe_gt_sriov_notice(gt, "Failed to push %u policy KLV%s (%pe)\n",81				   num_klvs, str_plural(num_klvs), ERR_PTR(err));82		xe_guc_klv_print(klvs, num_dwords, &p);83		return err;84	}85 86	return 0;87}88 89static int pf_push_policy_u32(struct xe_gt *gt, u16 key, u32 value)90{91	u32 klv[] = {92		PREP_GUC_KLV(key, 1),93		value,94	};95 96	return pf_push_policy_klvs(gt, 1, klv, ARRAY_SIZE(klv));97}98 99static int pf_update_policy_bool(struct xe_gt *gt, u16 key, bool *policy, bool value)100{101	int err;102 103	err = pf_push_policy_u32(gt, key, value);104	if (unlikely(err)) {105		xe_gt_sriov_notice(gt, "Failed to update policy %#x '%s' to '%s' (%pe)\n",106				   key, xe_guc_klv_key_to_string(key),107				   str_enabled_disabled(value), ERR_PTR(err));108		return err;109	}110 111	xe_gt_sriov_dbg(gt, "policy key %#x '%s' updated to '%s'\n",112			key, xe_guc_klv_key_to_string(key),113			str_enabled_disabled(value));114 115	*policy = value;116	return 0;117}118 119static int pf_update_policy_u32(struct xe_gt *gt, u16 key, u32 *policy, u32 value)120{121	int err;122 123	err = pf_push_policy_u32(gt, key, value);124	if (unlikely(err)) {125		xe_gt_sriov_notice(gt, "Failed to update policy %#x '%s' to '%s' (%pe)\n",126				   key, xe_guc_klv_key_to_string(key),127				   str_enabled_disabled(value), ERR_PTR(err));128		return err;129	}130 131	xe_gt_sriov_dbg(gt, "policy key %#x '%s' updated to %u\n",132			key, xe_guc_klv_key_to_string(key), value);133 134	*policy = value;135	return 0;136}137 138static int pf_provision_sched_if_idle(struct xe_gt *gt, bool enable)139{140	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));141	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));142 143	return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY,144				     &gt->sriov.pf.policy.guc.sched_if_idle,145				     enable);146}147 148static int pf_reprovision_sched_if_idle(struct xe_gt *gt)149{150	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));151	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));152 153	return pf_provision_sched_if_idle(gt, gt->sriov.pf.policy.guc.sched_if_idle);154}155 156static void pf_sanitize_sched_if_idle(struct xe_gt *gt)157{158	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));159	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));160 161	gt->sriov.pf.policy.guc.sched_if_idle = false;162}163 164/**165 * xe_gt_sriov_pf_policy_set_sched_if_idle - Control the 'sched_if_idle' policy.166 * @gt: the &xe_gt where to apply the policy167 * @enable: the value of the 'sched_if_idle' policy168 *169 * This function can only be called on PF.170 *171 * Return: 0 on success or a negative error code on failure.172 */173int xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt *gt, bool enable)174{175	int err;176 177	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));178	err = pf_provision_sched_if_idle(gt, enable);179	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));180 181	return err;182}183 184/**185 * xe_gt_sriov_pf_policy_get_sched_if_idle - Retrieve value of 'sched_if_idle' policy.186 * @gt: the &xe_gt where to read the policy from187 *188 * This function can only be called on PF.189 *190 * Return: value of 'sched_if_idle' policy.191 */192bool xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt *gt)193{194	bool enable;195 196	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));197 198	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));199	enable = gt->sriov.pf.policy.guc.sched_if_idle;200	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));201 202	return enable;203}204 205static int pf_provision_reset_engine(struct xe_gt *gt, bool enable)206{207	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));208	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));209 210	return pf_update_policy_bool(gt, GUC_KLV_VGT_POLICY_RESET_AFTER_VF_SWITCH_KEY,211				     &gt->sriov.pf.policy.guc.reset_engine, enable);212}213 214static int pf_reprovision_reset_engine(struct xe_gt *gt)215{216	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));217	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));218 219	return pf_provision_reset_engine(gt, gt->sriov.pf.policy.guc.reset_engine);220}221 222static void pf_sanitize_reset_engine(struct xe_gt *gt)223{224	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));225	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));226 227	gt->sriov.pf.policy.guc.reset_engine = false;228}229 230/**231 * xe_gt_sriov_pf_policy_set_reset_engine - Control the 'reset_engine' policy.232 * @gt: the &xe_gt where to apply the policy233 * @enable: the value of the 'reset_engine' policy234 *235 * This function can only be called on PF.236 *237 * Return: 0 on success or a negative error code on failure.238 */239int xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt *gt, bool enable)240{241	int err;242 243	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));244	err = pf_provision_reset_engine(gt, enable);245	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));246 247	return err;248}249 250/**251 * xe_gt_sriov_pf_policy_get_reset_engine - Retrieve value of 'reset_engine' policy.252 * @gt: the &xe_gt where to read the policy from253 *254 * This function can only be called on PF.255 *256 * Return: value of 'reset_engine' policy.257 */258bool xe_gt_sriov_pf_policy_get_reset_engine(struct xe_gt *gt)259{260	bool enable;261 262	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));263 264	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));265	enable = gt->sriov.pf.policy.guc.reset_engine;266	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));267 268	return enable;269}270 271static int pf_provision_sample_period(struct xe_gt *gt, u32 value)272{273	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));274	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));275 276	return pf_update_policy_u32(gt, GUC_KLV_VGT_POLICY_ADVERSE_SAMPLE_PERIOD_KEY,277				    &gt->sriov.pf.policy.guc.sample_period, value);278}279 280static int pf_reprovision_sample_period(struct xe_gt *gt)281{282	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));283	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));284 285	return pf_provision_sample_period(gt, gt->sriov.pf.policy.guc.sample_period);286}287 288static void pf_sanitize_sample_period(struct xe_gt *gt)289{290	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));291	lockdep_assert_held(xe_gt_sriov_pf_master_mutex(gt));292 293	gt->sriov.pf.policy.guc.sample_period = 0;294}295 296/**297 * xe_gt_sriov_pf_policy_set_sample_period - Control the 'sample_period' policy.298 * @gt: the &xe_gt where to apply the policy299 * @value: the value of the 'sample_period' policy300 *301 * This function can only be called on PF.302 *303 * Return: 0 on success or a negative error code on failure.304 */305int xe_gt_sriov_pf_policy_set_sample_period(struct xe_gt *gt, u32 value)306{307	int err;308 309	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));310	err = pf_provision_sample_period(gt, value);311	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));312 313	return err;314}315 316/**317 * xe_gt_sriov_pf_policy_get_sample_period - Retrieve value of 'sample_period' policy.318 * @gt: the &xe_gt where to read the policy from319 *320 * This function can only be called on PF.321 *322 * Return: value of 'sample_period' policy.323 */324u32 xe_gt_sriov_pf_policy_get_sample_period(struct xe_gt *gt)325{326	u32 value;327 328	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));329 330	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));331	value = gt->sriov.pf.policy.guc.sample_period;332	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));333 334	return value;335}336 337static void pf_sanitize_guc_policies(struct xe_gt *gt)338{339	pf_sanitize_sched_if_idle(gt);340	pf_sanitize_reset_engine(gt);341	pf_sanitize_sample_period(gt);342}343 344/**345 * xe_gt_sriov_pf_policy_sanitize - Reset policy settings.346 * @gt: the &xe_gt347 *348 * This function can only be called on PF.349 *350 * Return: 0 on success or a negative error code on failure.351 */352void xe_gt_sriov_pf_policy_sanitize(struct xe_gt *gt)353{354	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));355	pf_sanitize_guc_policies(gt);356	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));357}358 359/**360 * xe_gt_sriov_pf_policy_reprovision - Reprovision (and optionally reset) policy settings.361 * @gt: the &xe_gt362 * @reset: if true will reprovision using default values instead of latest363 *364 * This function can only be called on PF.365 *366 * Return: 0 on success or a negative error code on failure.367 */368int xe_gt_sriov_pf_policy_reprovision(struct xe_gt *gt, bool reset)369{370	int err = 0;371 372	xe_pm_runtime_get_noresume(gt_to_xe(gt));373 374	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));375	if (reset)376		pf_sanitize_guc_policies(gt);377	err |= pf_reprovision_sched_if_idle(gt);378	err |= pf_reprovision_reset_engine(gt);379	err |= pf_reprovision_sample_period(gt);380	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));381 382	xe_pm_runtime_put(gt_to_xe(gt));383 384	return err ? -ENXIO : 0;385}386 387static void print_guc_policies(struct drm_printer *p, struct xe_gt_sriov_guc_policies *policy)388{389	drm_printf(p, "%s:\t%s\n",390		   xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_SCHED_IF_IDLE_KEY),391		   str_enabled_disabled(policy->sched_if_idle));392	drm_printf(p, "%s:\t%s\n",393		   xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_RESET_AFTER_VF_SWITCH_KEY),394		   str_enabled_disabled(policy->reset_engine));395	drm_printf(p, "%s:\t%u %s\n",396		   xe_guc_klv_key_to_string(GUC_KLV_VGT_POLICY_ADVERSE_SAMPLE_PERIOD_KEY),397		   policy->sample_period, policy->sample_period ? "ms" : "(disabled)");398}399 400/**401 * xe_gt_sriov_pf_policy_print - Dump actual policy values.402 * @gt: the &xe_gt where to read the policy from403 * @p: the &drm_printer404 *405 * This function can only be called on PF.406 *407 * Return: 0 on success or a negative error code on failure.408 */409int xe_gt_sriov_pf_policy_print(struct xe_gt *gt, struct drm_printer *p)410{411	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));412 413	mutex_lock(xe_gt_sriov_pf_master_mutex(gt));414	print_guc_policies(p, &gt->sriov.pf.policy.guc);415	mutex_unlock(xe_gt_sriov_pf_master_mutex(gt));416 417	return 0;418}419