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  */
guc_action_update_vgt_policy(struct xe_guc * guc,u64 addr,u32 size)22 static 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  */
pf_send_policy_klvs(struct xe_gt * gt,struct xe_guc_buf buf,u32 num_dwords)38 static 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  */
pf_push_policy_buf_klvs(struct xe_gt * gt,u32 num_klvs,struct xe_guc_buf buf,u32 num_dwords)49 static 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  */
pf_push_policy_klvs(struct xe_gt * gt,u32 num_klvs,const u32 * klvs,u32 num_dwords)74 static 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 
pf_push_policy_u32(struct xe_gt * gt,u16 key,u32 value)87 static 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 
pf_update_policy_bool(struct xe_gt * gt,u16 key,bool * policy,bool value)97 static 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 
pf_update_policy_u32(struct xe_gt * gt,u16 key,u32 * policy,u32 value)117 static 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 
pf_bulk_reset_sched_priority(struct xe_gt * gt,u32 priority)136 static 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 
pf_provision_sched_if_idle(struct xe_gt * gt,bool enable)148 static 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 
pf_reprovision_sched_if_idle(struct xe_gt * gt)165 static 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 
pf_sanitize_sched_if_idle(struct xe_gt * gt)173 static 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  */
xe_gt_sriov_pf_policy_set_sched_if_idle(struct xe_gt * gt,bool enable)190 int 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  */
xe_gt_sriov_pf_policy_get_sched_if_idle(struct xe_gt * gt)209 bool 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 
pf_provision_reset_engine(struct xe_gt * gt,bool enable)222 static 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 
pf_reprovision_reset_engine(struct xe_gt * gt)231 static 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 
pf_sanitize_reset_engine(struct xe_gt * gt)239 static 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  */
xe_gt_sriov_pf_policy_set_reset_engine(struct xe_gt * gt,bool enable)256 int 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  */
xe_gt_sriov_pf_policy_get_reset_engine(struct xe_gt * gt)275 bool 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 
pf_provision_sample_period(struct xe_gt * gt,u32 value)288 static 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 
pf_reprovision_sample_period(struct xe_gt * gt)297 static 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 
pf_sanitize_sample_period(struct xe_gt * gt)305 static 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  */
xe_gt_sriov_pf_policy_set_sample_period(struct xe_gt * gt,u32 value)322 int 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  */
xe_gt_sriov_pf_policy_get_sample_period(struct xe_gt * gt)341 u32 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 
pf_sanitize_guc_policies(struct xe_gt * gt)354 static 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  */
xe_gt_sriov_pf_policy_sanitize(struct xe_gt * gt)369 void 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  */
xe_gt_sriov_pf_policy_reprovision(struct xe_gt * gt,bool reset)385 int 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 
print_guc_policies(struct drm_printer * p,struct xe_gt_sriov_guc_policies * policy)404 static 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  */
xe_gt_sriov_pf_policy_print(struct xe_gt * gt,struct drm_printer * p)426 int 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 }
436