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