xref: /linux/drivers/gpu/drm/xe/xe_sriov_pf_provision.c (revision face6a3615a649456eb4549f6d474221d877d604)
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_sriov.h"
10 #include "xe_sriov_pf_helpers.h"
11 #include "xe_sriov_pf_provision.h"
12 #include "xe_sriov_pf_provision_types.h"
13 #include "xe_sriov_printk.h"
14 
15 static const char *mode_to_string(enum xe_sriov_provisioning_mode mode)
16 {
17 	switch (mode) {
18 	case XE_SRIOV_PROVISIONING_MODE_AUTO:
19 		return "auto";
20 	case XE_SRIOV_PROVISIONING_MODE_CUSTOM:
21 		return "custom";
22 	default:
23 		return "<invalid>";
24 	}
25 }
26 
27 static bool pf_auto_provisioning_mode(struct xe_device *xe)
28 {
29 	xe_assert(xe, IS_SRIOV_PF(xe));
30 
31 	return xe->sriov.pf.provision.mode == XE_SRIOV_PROVISIONING_MODE_AUTO;
32 }
33 
34 static bool pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs)
35 {
36 	unsigned int n;
37 
38 	for (n = 1; n <= num_vfs; n++)
39 		if (!xe_gt_sriov_pf_config_is_empty(gt, n))
40 			return false;
41 
42 	return true;
43 }
44 
45 static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
46 {
47 	struct xe_gt *gt;
48 	unsigned int id;
49 	int result = 0;
50 	int err;
51 
52 	for_each_gt(gt, xe, id) {
53 		if (!pf_needs_provisioning(gt, num_vfs))
54 			return -EUCLEAN;
55 		err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
56 		result = result ?: err;
57 	}
58 
59 	return result;
60 }
61 
62 static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
63 {
64 	struct xe_gt *gt;
65 	unsigned int id;
66 	unsigned int n;
67 
68 	for_each_gt(gt, xe, id)
69 		for (n = 1; n <= num_vfs; n++)
70 			xe_gt_sriov_pf_config_release(gt, n, true);
71 }
72 
73 static void pf_unprovision_all_vfs(struct xe_device *xe)
74 {
75 	pf_unprovision_vfs(xe, xe_sriov_pf_get_totalvfs(xe));
76 }
77 
78 /**
79  * xe_sriov_pf_provision_vfs() - Provision VFs in auto-mode.
80  * @xe: the PF &xe_device
81  * @num_vfs: the number of VFs to auto-provision
82  *
83  * This function can only be called on PF.
84  *
85  * Return: 0 on success or a negative error code on failure.
86  */
87 int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
88 {
89 	xe_assert(xe, IS_SRIOV_PF(xe));
90 
91 	if (!pf_auto_provisioning_mode(xe))
92 		return 0;
93 
94 	return pf_provision_vfs(xe, num_vfs);
95 }
96 
97 /**
98  * xe_sriov_pf_unprovision_vfs() - Unprovision VFs in auto-mode.
99  * @xe: the PF &xe_device
100  * @num_vfs: the number of VFs to unprovision
101  *
102  * This function can only be called on PF.
103  *
104  * Return: 0 on success or a negative error code on failure.
105  */
106 int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
107 {
108 	xe_assert(xe, IS_SRIOV_PF(xe));
109 
110 	if (!pf_auto_provisioning_mode(xe))
111 		return 0;
112 
113 	pf_unprovision_vfs(xe, num_vfs);
114 	return 0;
115 }
116 
117 /**
118  * xe_sriov_pf_provision_set_mode() - Change VFs provision mode.
119  * @xe: the PF &xe_device
120  * @mode: the new VFs provisioning mode
121  *
122  * When changing from AUTO to CUSTOM mode, any already allocated VFs resources
123  * will remain allocated and will not be released upon VFs disabling.
124  *
125  * When changing back to AUTO mode, if VFs are not enabled, already allocated
126  * VFs resources will be immediately released. If VFs are still enabled, such
127  * mode change is rejected.
128  *
129  * This function can only be called on PF.
130  *
131  * Return: 0 on success or a negative error code on failure.
132  */
133 int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode)
134 {
135 	xe_assert(xe, IS_SRIOV_PF(xe));
136 
137 	if (mode == xe->sriov.pf.provision.mode)
138 		return 0;
139 
140 	if (mode == XE_SRIOV_PROVISIONING_MODE_AUTO) {
141 		if (xe_sriov_pf_num_vfs(xe)) {
142 			xe_sriov_dbg(xe, "can't restore %s: VFs must be disabled!\n",
143 				     mode_to_string(mode));
144 			return -EBUSY;
145 		}
146 		pf_unprovision_all_vfs(xe);
147 	}
148 
149 	xe_sriov_dbg(xe, "mode %s changed to %s by %ps\n",
150 		     mode_to_string(xe->sriov.pf.provision.mode),
151 		     mode_to_string(mode), __builtin_return_address(0));
152 	xe->sriov.pf.provision.mode = mode;
153 	return 0;
154 }
155