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 */
21static 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 */
37static 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 */
67static 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
89static 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
99static 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
119static 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
138static 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
148static 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
156static 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 */
173int 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 */
192bool 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
205static 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
214static 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
222static 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 */
239int 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 */
258bool 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
271static 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
280static 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
288static 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 */
305int 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 */
324u32 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
337static 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 */
352void 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 */
368int 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
387static 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 */
409int 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