File Index
Files and directories
Sign in
FILE

xe_sriov_pf_provision.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_sriov_pf_provision.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2025 Intel Corporation
  4 */
  5
  6#include "xe_assert.h"
  7#include "xe_device.h"
  8#include "xe_gt_sriov_pf_config.h"
  9#include "xe_gt_sriov_pf_policy.h"
 10#include "xe_sriov.h"
 11#include "xe_sriov_pf_helpers.h"
 12#include "xe_sriov_pf_provision.h"
 13#include "xe_sriov_pf_provision_types.h"
 14#include "xe_sriov_printk.h"
 15
 16static const char *mode_to_string(enum xe_sriov_provisioning_mode mode)
 17{
 18	switch (mode) {
 19	case XE_SRIOV_PROVISIONING_MODE_AUTO:
 20		return "auto";
 21	case XE_SRIOV_PROVISIONING_MODE_CUSTOM:
 22		return "custom";
 23	default:
 24		return "<invalid>";
 25	}
 26}
 27
 28static bool pf_auto_provisioning_mode(struct xe_device *xe)
 29{
 30	xe_assert(xe, IS_SRIOV_PF(xe));
 31
 32	return xe->sriov.pf.provision.mode == XE_SRIOV_PROVISIONING_MODE_AUTO;
 33}
 34
 35static bool pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs)
 36{
 37	unsigned int n;
 38
 39	for (n = 1; n <= num_vfs; n++)
 40		if (!xe_gt_sriov_pf_config_is_empty(gt, n))
 41			return false;
 42
 43	return true;
 44}
 45
 46static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
 47{
 48	struct xe_gt *gt;
 49	unsigned int id;
 50	int result = 0;
 51	int err;
 52
 53	for_each_gt(gt, xe, id) {
 54		if (!pf_needs_provisioning(gt, num_vfs))
 55			return -EUCLEAN;
 56		err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
 57		result = result ?: err;
 58	}
 59
 60	return result;
 61}
 62
 63static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
 64{
 65	struct xe_gt *gt;
 66	unsigned int id;
 67	unsigned int n;
 68
 69	for_each_gt(gt, xe, id)
 70		for (n = 1; n <= num_vfs; n++)
 71			xe_gt_sriov_pf_config_release(gt, n, true);
 72}
 73
 74static void pf_unprovision_all_vfs(struct xe_device *xe)
 75{
 76	pf_unprovision_vfs(xe, xe_sriov_pf_get_totalvfs(xe));
 77}
 78
 79/**
 80 * xe_sriov_pf_provision_vfs() - Provision VFs in auto-mode.
 81 * @xe: the PF &xe_device
 82 * @num_vfs: the number of VFs to auto-provision
 83 *
 84 * This function can only be called on PF.
 85 *
 86 * Return: 0 on success or a negative error code on failure.
 87 */
 88int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
 89{
 90	xe_assert(xe, IS_SRIOV_PF(xe));
 91
 92	if (!pf_auto_provisioning_mode(xe))
 93		return 0;
 94
 95	return pf_provision_vfs(xe, num_vfs);
 96}
 97
 98/**
 99 * xe_sriov_pf_unprovision_vfs() - Unprovision VFs in auto-mode.
100 * @xe: the PF &xe_device
101 * @num_vfs: the number of VFs to unprovision
102 *
103 * This function can only be called on PF.
104 *
105 * Return: 0 on success or a negative error code on failure.
106 */
107int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
108{
109	xe_assert(xe, IS_SRIOV_PF(xe));
110
111	if (!pf_auto_provisioning_mode(xe))
112		return 0;
113
114	pf_unprovision_vfs(xe, num_vfs);
115	return 0;
116}
117
118/**
119 * xe_sriov_pf_provision_set_mode() - Change VFs provision mode.
120 * @xe: the PF &xe_device
121 * @mode: the new VFs provisioning mode
122 *
123 * When changing from AUTO to CUSTOM mode, any already allocated VFs resources
124 * will remain allocated and will not be released upon VFs disabling.
125 *
126 * When changing back to AUTO mode, if VFs are not enabled, already allocated
127 * VFs resources will be immediately released. If VFs are still enabled, such
128 * mode change is rejected.
129 *
130 * This function can only be called on PF.
131 *
132 * Return: 0 on success or a negative error code on failure.
133 */
134int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode)
135{
136	xe_assert(xe, IS_SRIOV_PF(xe));
137
138	if (mode == xe->sriov.pf.provision.mode)
139		return 0;
140
141	if (mode == XE_SRIOV_PROVISIONING_MODE_AUTO) {
142		if (xe_sriov_pf_num_vfs(xe)) {
143			xe_sriov_dbg(xe, "can't restore %s: VFs must be disabled!\n",
144				     mode_to_string(mode));
145			return -EBUSY;
146		}
147		pf_unprovision_all_vfs(xe);
148	}
149
150	xe_sriov_dbg(xe, "mode %s changed to %s by %ps\n",
151		     mode_to_string(xe->sriov.pf.provision.mode),
152		     mode_to_string(mode), __builtin_return_address(0));
153	xe->sriov.pf.provision.mode = mode;
154	return 0;
155}
156
157/**
158 * xe_sriov_pf_provision_bulk_apply_eq() - Change execution quantum for all VFs and PF.
159 * @xe: the PF &xe_device
160 * @eq: execution quantum in [ms] to set
161 *
162 * Change execution quantum (EQ) provisioning on all tiles/GTs.
163 *
164 * This function can only be called on PF.
165 *
166 * Return: 0 on success or a negative error code on failure.
167 */
168int xe_sriov_pf_provision_bulk_apply_eq(struct xe_device *xe, u32 eq)
169{
170	struct xe_gt *gt;
171	unsigned int id;
172	int result = 0;
173	int err;
174
175	guard(mutex)(xe_sriov_pf_master_mutex(xe));
176
177	for_each_gt(gt, xe, id) {
178		err = xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(gt, eq);
179		result = result ?: err;
180	}
181
182	return result;
183}
184
185/**
186 * xe_sriov_pf_provision_apply_vf_eq() - Change VF's execution quantum.
187 * @xe: the PF &xe_device
188 * @vfid: the VF identifier
189 * @eq: execution quantum in [ms] to set
190 *
191 * Change VF's execution quantum (EQ) provisioning on all tiles/GTs.
192 *
193 * This function can only be called on PF.
194 *
195 * Return: 0 on success or a negative error code on failure.
196 */
197int xe_sriov_pf_provision_apply_vf_eq(struct xe_device *xe, unsigned int vfid, u32 eq)
198{
199	struct xe_gt *gt;
200	unsigned int id;
201	int result = 0;
202	int err;
203
204	guard(mutex)(xe_sriov_pf_master_mutex(xe));
205
206	for_each_gt(gt, xe, id) {
207		err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, vfid, eq);
208		result = result ?: err;
209	}
210
211	return result;
212}
213
214static int pf_report_unclean(struct xe_gt *gt, unsigned int vfid,
215			     const char *what, u32 found, u32 expected)
216{
217	char name[8];
218
219	xe_sriov_dbg(gt_to_xe(gt), "%s on GT%u has %s=%u (expected %u)\n",
220		     xe_sriov_function_name(vfid, name, sizeof(name)),
221		     gt->info.id, what, found, expected);
222	return -EUCLEAN;
223}
224
225/**
226 * xe_sriov_pf_provision_query_vf_eq() - Query VF's execution quantum.
227 * @xe: the PF &xe_device
228 * @vfid: the VF identifier
229 * @eq: placeholder for the returned execution quantum in [ms]
230 *
231 * Query VF's execution quantum (EQ) provisioning from all tiles/GTs.
232 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned.
233 *
234 * This function can only be called on PF.
235 *
236 * Return: 0 on success or a negative error code on failure.
237 */
238int xe_sriov_pf_provision_query_vf_eq(struct xe_device *xe, unsigned int vfid, u32 *eq)
239{
240	struct xe_gt *gt;
241	unsigned int id;
242	int count = 0;
243	u32 value;
244
245	guard(mutex)(xe_sriov_pf_master_mutex(xe));
246
247	for_each_gt(gt, xe, id) {
248		value = xe_gt_sriov_pf_config_get_exec_quantum_locked(gt, vfid);
249		if (!count++)
250			*eq = value;
251		else if (value != *eq)
252			return pf_report_unclean(gt, vfid, "EQ", value, *eq);
253	}
254
255	return !count ? -ENODATA : 0;
256}
257
258/**
259 * xe_sriov_pf_provision_bulk_apply_pt() - Change preemption timeout for all VFs and PF.
260 * @xe: the PF &xe_device
261 * @pt: preemption timeout in [us] to set
262 *
263 * Change preemption timeout (PT) provisioning on all tiles/GTs.
264 *
265 * This function can only be called on PF.
266 *
267 * Return: 0 on success or a negative error code on failure.
268 */
269int xe_sriov_pf_provision_bulk_apply_pt(struct xe_device *xe, u32 pt)
270{
271	struct xe_gt *gt;
272	unsigned int id;
273	int result = 0;
274	int err;
275
276	guard(mutex)(xe_sriov_pf_master_mutex(xe));
277
278	for_each_gt(gt, xe, id) {
279		err = xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(gt, pt);
280		result = result ?: err;
281	}
282
283	return result;
284}
285
286/**
287 * xe_sriov_pf_provision_apply_vf_pt() - Change VF's preemption timeout.
288 * @xe: the PF &xe_device
289 * @vfid: the VF identifier
290 * @pt: preemption timeout in [us] to set
291 *
292 * Change VF's preemption timeout (PT) provisioning on all tiles/GTs.
293 *
294 * This function can only be called on PF.
295 *
296 * Return: 0 on success or a negative error code on failure.
297 */
298int xe_sriov_pf_provision_apply_vf_pt(struct xe_device *xe, unsigned int vfid, u32 pt)
299{
300	struct xe_gt *gt;
301	unsigned int id;
302	int result = 0;
303	int err;
304
305	guard(mutex)(xe_sriov_pf_master_mutex(xe));
306
307	for_each_gt(gt, xe, id) {
308		err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, vfid, pt);
309		result = result ?: err;
310	}
311
312	return result;
313}
314
315/**
316 * xe_sriov_pf_provision_query_vf_pt() - Query VF's preemption timeout.
317 * @xe: the PF &xe_device
318 * @vfid: the VF identifier
319 * @pt: placeholder for the returned preemption timeout in [us]
320 *
321 * Query VF's preemption timeout (PT) provisioning from all tiles/GTs.
322 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned.
323 *
324 * This function can only be called on PF.
325 *
326 * Return: 0 on success or a negative error code on failure.
327 */
328int xe_sriov_pf_provision_query_vf_pt(struct xe_device *xe, unsigned int vfid, u32 *pt)
329{
330	struct xe_gt *gt;
331	unsigned int id;
332	int count = 0;
333	u32 value;
334
335	guard(mutex)(xe_sriov_pf_master_mutex(xe));
336
337	for_each_gt(gt, xe, id) {
338		value = xe_gt_sriov_pf_config_get_preempt_timeout_locked(gt, vfid);
339		if (!count++)
340			*pt = value;
341		else if (value != *pt)
342			return pf_report_unclean(gt, vfid, "PT", value, *pt);
343	}
344
345	return !count ? -ENODATA : 0;
346}
347
348/**
349 * xe_sriov_pf_provision_bulk_apply_priority() - Change scheduling priority of all VFs and PF.
350 * @xe: the PF &xe_device
351 * @prio: scheduling priority to set
352 *
353 * Change the scheduling priority provisioning on all tiles/GTs.
354 *
355 * This function can only be called on PF.
356 *
357 * Return: 0 on success or a negative error code on failure.
358 */
359int xe_sriov_pf_provision_bulk_apply_priority(struct xe_device *xe, u32 prio)
360{
361	bool sched_if_idle;
362	struct xe_gt *gt;
363	unsigned int id;
364	int result = 0;
365	int err;
366
367	/*
368	 * Currently, priority changes that involves VFs are only allowed using
369	 * the 'sched_if_idle' policy KLV, so only LOW and NORMAL are supported.
370	 */
371	xe_assert(xe, prio < GUC_SCHED_PRIORITY_HIGH);
372	sched_if_idle = prio == GUC_SCHED_PRIORITY_NORMAL;
373
374	for_each_gt(gt, xe, id) {
375		err = xe_gt_sriov_pf_policy_set_sched_if_idle(gt, sched_if_idle);
376		result = result ?: err;
377	}
378
379	return result;
380}
381
382/**
383 * xe_sriov_pf_provision_apply_vf_priority() - Change VF's scheduling priority.
384 * @xe: the PF &xe_device
385 * @vfid: the VF identifier
386 * @prio: scheduling priority to set
387 *
388 * Change VF's scheduling priority provisioning on all tiles/GTs.
389 *
390 * This function can only be called on PF.
391 *
392 * Return: 0 on success or a negative error code on failure.
393 */
394int xe_sriov_pf_provision_apply_vf_priority(struct xe_device *xe, unsigned int vfid, u32 prio)
395{
396	struct xe_gt *gt;
397	unsigned int id;
398	int result = 0;
399	int err;
400
401	for_each_gt(gt, xe, id) {
402		err = xe_gt_sriov_pf_config_set_sched_priority(gt, vfid, prio);
403		result = result ?: err;
404	}
405
406	return result;
407}
408
409/**
410 * xe_sriov_pf_provision_query_vf_priority() - Query VF's scheduling priority.
411 * @xe: the PF &xe_device
412 * @vfid: the VF identifier
413 * @prio: placeholder for the returned scheduling priority
414 *
415 * Query VF's scheduling priority provisioning from all tiles/GTs.
416 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned.
417 *
418 * This function can only be called on PF.
419 *
420 * Return: 0 on success or a negative error code on failure.
421 */
422int xe_sriov_pf_provision_query_vf_priority(struct xe_device *xe, unsigned int vfid, u32 *prio)
423{
424	struct xe_gt *gt;
425	unsigned int id;
426	int count = 0;
427	u32 value;
428
429	for_each_gt(gt, xe, id) {
430		value = xe_gt_sriov_pf_config_get_sched_priority(gt, vfid);
431		if (!count++)
432			*prio = value;
433		else if (value != *prio)
434			return pf_report_unclean(gt, vfid, "priority", value, *prio);
435	}
436
437	return !count ? -ENODATA : 0;
438}
~/ Read-only file preview.