File Index
Files and directories
Sign in
FILE

xe_gt_sriov_pf_policy.c

File preview with syntax highlighting.

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