xref: /linux/drivers/gpu/drm/xe/xe_pci_sriov.c (revision e78f70bad29c5ae1e1076698b690b15794e9b81e)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023-2024 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_control.h"
10 #include "xe_gt_sriov_printk.h"
11 #include "xe_guc_engine_activity.h"
12 #include "xe_pci_sriov.h"
13 #include "xe_pm.h"
14 #include "xe_sriov.h"
15 #include "xe_sriov_pf_helpers.h"
16 #include "xe_sriov_printk.h"
17 
18 static int pf_needs_provisioning(struct xe_gt *gt, unsigned int num_vfs)
19 {
20 	unsigned int n;
21 
22 	for (n = 1; n <= num_vfs; n++)
23 		if (!xe_gt_sriov_pf_config_is_empty(gt, n))
24 			return false;
25 
26 	return true;
27 }
28 
29 static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs)
30 {
31 	struct xe_gt *gt;
32 	unsigned int id;
33 	int result = 0, err;
34 
35 	for_each_gt(gt, xe, id) {
36 		if (!pf_needs_provisioning(gt, num_vfs))
37 			continue;
38 		err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs);
39 		result = result ?: err;
40 	}
41 
42 	return result;
43 }
44 
45 static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs)
46 {
47 	struct xe_gt *gt;
48 	unsigned int id;
49 	unsigned int n;
50 
51 	for_each_gt(gt, xe, id)
52 		for (n = 1; n <= num_vfs; n++)
53 			xe_gt_sriov_pf_config_release(gt, n, true);
54 }
55 
56 static void pf_reset_vfs(struct xe_device *xe, unsigned int num_vfs)
57 {
58 	struct xe_gt *gt;
59 	unsigned int id;
60 	unsigned int n;
61 
62 	for_each_gt(gt, xe, id)
63 		for (n = 1; n <= num_vfs; n++)
64 			xe_gt_sriov_pf_control_trigger_flr(gt, n);
65 }
66 
67 static struct pci_dev *xe_pci_pf_get_vf_dev(struct xe_device *xe, unsigned int vf_id)
68 {
69 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
70 
71 	xe_assert(xe, IS_SRIOV_PF(xe));
72 
73 	/* caller must use pci_dev_put() */
74 	return pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
75 			pdev->bus->number,
76 			pci_iov_virtfn_devfn(pdev, vf_id));
77 }
78 
79 static void pf_link_vfs(struct xe_device *xe, int num_vfs)
80 {
81 	struct pci_dev *pdev_pf = to_pci_dev(xe->drm.dev);
82 	struct device_link *link;
83 	struct pci_dev *pdev_vf;
84 	unsigned int n;
85 
86 	/*
87 	 * When both PF and VF devices are enabled on the host, during system
88 	 * resume they are resuming in parallel.
89 	 *
90 	 * But PF has to complete the provision of VF first to allow any VFs to
91 	 * successfully resume.
92 	 *
93 	 * Create a parent-child device link between PF and VF devices that will
94 	 * enforce correct resume order.
95 	 */
96 	for (n = 1; n <= num_vfs; n++) {
97 		pdev_vf = xe_pci_pf_get_vf_dev(xe, n - 1);
98 
99 		/* unlikely, something weird is happening, abort */
100 		if (!pdev_vf) {
101 			xe_sriov_err(xe, "Cannot find VF%u device, aborting link%s creation!\n",
102 				     n, str_plural(num_vfs));
103 			break;
104 		}
105 
106 		link = device_link_add(&pdev_vf->dev, &pdev_pf->dev,
107 				       DL_FLAG_AUTOREMOVE_CONSUMER);
108 		/* unlikely and harmless, continue with other VFs */
109 		if (!link)
110 			xe_sriov_notice(xe, "Failed linking VF%u\n", n);
111 
112 		pci_dev_put(pdev_vf);
113 	}
114 }
115 
116 static void pf_engine_activity_stats(struct xe_device *xe, unsigned int num_vfs, bool enable)
117 {
118 	struct xe_gt *gt;
119 	unsigned int id;
120 	int ret = 0;
121 
122 	for_each_gt(gt, xe, id) {
123 		ret = xe_guc_engine_activity_function_stats(&gt->uc.guc, num_vfs, enable);
124 		if (ret)
125 			xe_gt_sriov_info(gt, "Failed to %s engine activity function stats (%pe)\n",
126 					 str_enable_disable(enable), ERR_PTR(ret));
127 	}
128 }
129 
130 static int pf_enable_vfs(struct xe_device *xe, int num_vfs)
131 {
132 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
133 	int total_vfs = xe_sriov_pf_get_totalvfs(xe);
134 	int err;
135 
136 	xe_assert(xe, IS_SRIOV_PF(xe));
137 	xe_assert(xe, num_vfs > 0);
138 	xe_assert(xe, num_vfs <= total_vfs);
139 	xe_sriov_dbg(xe, "enabling %u VF%s\n", num_vfs, str_plural(num_vfs));
140 
141 	/*
142 	 * We must hold additional reference to the runtime PM to keep PF in D0
143 	 * during VFs lifetime, as our VFs do not implement the PM capability.
144 	 *
145 	 * With PF being in D0 state, all VFs will also behave as in D0 state.
146 	 * This will also keep GuC alive with all VFs' configurations.
147 	 *
148 	 * We will release this additional PM reference in pf_disable_vfs().
149 	 */
150 	xe_pm_runtime_get_noresume(xe);
151 
152 	err = pf_provision_vfs(xe, num_vfs);
153 	if (err < 0)
154 		goto failed;
155 
156 	err = pci_enable_sriov(pdev, num_vfs);
157 	if (err < 0)
158 		goto failed;
159 
160 	pf_link_vfs(xe, num_vfs);
161 
162 	xe_sriov_info(xe, "Enabled %u of %u VF%s\n",
163 		      num_vfs, total_vfs, str_plural(total_vfs));
164 
165 	pf_engine_activity_stats(xe, num_vfs, true);
166 
167 	return num_vfs;
168 
169 failed:
170 	pf_unprovision_vfs(xe, num_vfs);
171 	xe_pm_runtime_put(xe);
172 
173 	xe_sriov_notice(xe, "Failed to enable %u VF%s (%pe)\n",
174 			num_vfs, str_plural(num_vfs), ERR_PTR(err));
175 	return err;
176 }
177 
178 static int pf_disable_vfs(struct xe_device *xe)
179 {
180 	struct device *dev = xe->drm.dev;
181 	struct pci_dev *pdev = to_pci_dev(dev);
182 	u16 num_vfs = pci_num_vf(pdev);
183 
184 	xe_assert(xe, IS_SRIOV_PF(xe));
185 	xe_sriov_dbg(xe, "disabling %u VF%s\n", num_vfs, str_plural(num_vfs));
186 
187 	if (!num_vfs)
188 		return 0;
189 
190 	pf_engine_activity_stats(xe, num_vfs, false);
191 
192 	pci_disable_sriov(pdev);
193 
194 	pf_reset_vfs(xe, num_vfs);
195 
196 	pf_unprovision_vfs(xe, num_vfs);
197 
198 	/* not needed anymore - see pf_enable_vfs() */
199 	xe_pm_runtime_put(xe);
200 
201 	xe_sriov_info(xe, "Disabled %u VF%s\n", num_vfs, str_plural(num_vfs));
202 	return 0;
203 }
204 
205 /**
206  * xe_pci_sriov_configure - Configure SR-IOV (enable/disable VFs).
207  * @pdev: the &pci_dev
208  * @num_vfs: number of VFs to enable or zero to disable all VFs
209  *
210  * This is the Xe implementation of struct pci_driver.sriov_configure callback.
211  *
212  * This callback will be called by the PCI subsystem to enable or disable SR-IOV
213  * Virtual Functions (VFs) as requested by the used via the PCI sysfs interface.
214  *
215  * Return: number of configured VFs or a negative error code on failure.
216  */
217 int xe_pci_sriov_configure(struct pci_dev *pdev, int num_vfs)
218 {
219 	struct xe_device *xe = pdev_to_xe_device(pdev);
220 	int ret;
221 
222 	if (!IS_SRIOV_PF(xe))
223 		return -ENODEV;
224 
225 	if (num_vfs < 0)
226 		return -EINVAL;
227 
228 	if (num_vfs > xe_sriov_pf_get_totalvfs(xe))
229 		return -ERANGE;
230 
231 	if (num_vfs && pci_num_vf(pdev))
232 		return -EBUSY;
233 
234 	xe_pm_runtime_get(xe);
235 	if (num_vfs > 0)
236 		ret = pf_enable_vfs(xe, num_vfs);
237 	else
238 		ret = pf_disable_vfs(xe);
239 	xe_pm_runtime_put(xe);
240 
241 	return ret;
242 }
243