File Index
Files and directories
Sign in
FILE

selftest_slpc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/i915/gt/selftest_slpc.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2021 Intel Corporation
  4 */
  5
  6#define NUM_STEPS 5
  7#define H2G_DELAY 50000
  8#define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000)
  9#define FREQUENCY_REQ_UNIT	DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \
 10						  GEN9_FREQ_SCALER)
 11enum test_type {
 12	VARY_MIN,
 13	VARY_MAX,
 14	MAX_GRANTED,
 15	SLPC_POWER,
 16	TILE_INTERACTION,
 17};
 18
 19struct slpc_thread {
 20	struct kthread_worker *worker;
 21	struct kthread_work work;
 22	struct intel_gt *gt;
 23	int result;
 24};
 25
 26static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
 27{
 28	int ret;
 29
 30	ret = intel_guc_slpc_set_min_freq(slpc, freq);
 31	if (ret)
 32		pr_err("Could not set min frequency to [%u]\n", freq);
 33	else /* Delay to ensure h2g completes */
 34		delay_for_h2g();
 35
 36	return ret;
 37}
 38
 39static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
 40{
 41	int ret;
 42
 43	ret = intel_guc_slpc_set_max_freq(slpc, freq);
 44	if (ret)
 45		pr_err("Could not set maximum frequency [%u]\n",
 46		       freq);
 47	else /* Delay to ensure h2g completes */
 48		delay_for_h2g();
 49
 50	return ret;
 51}
 52
 53static int slpc_set_freq(struct intel_gt *gt, u32 freq)
 54{
 55	int err;
 56	struct intel_guc_slpc *slpc = &gt_to_guc(gt)->slpc;
 57
 58	err = slpc_set_max_freq(slpc, freq);
 59	if (err) {
 60		pr_err("Unable to update max freq");
 61		return err;
 62	}
 63
 64	err = slpc_set_min_freq(slpc, freq);
 65	if (err) {
 66		pr_err("Unable to update min freq");
 67		return err;
 68	}
 69
 70	return err;
 71}
 72
 73static int slpc_restore_freq(struct intel_guc_slpc *slpc, u32 min, u32 max)
 74{
 75	int err;
 76
 77	err = slpc_set_max_freq(slpc, max);
 78	if (err) {
 79		pr_err("Unable to restore max freq");
 80		return err;
 81	}
 82
 83	err = slpc_set_min_freq(slpc, min);
 84	if (err) {
 85		pr_err("Unable to restore min freq");
 86		return err;
 87	}
 88
 89	err = intel_guc_slpc_set_ignore_eff_freq(slpc, false);
 90	if (err) {
 91		pr_err("Unable to restore efficient freq");
 92		return err;
 93	}
 94
 95	return 0;
 96}
 97
 98static u64 slpc_measure_power(struct intel_rps *rps, int *freq)
 99{
100	u64 x[5];
101	int i;
102
103	for (i = 0; i < 5; i++)
104		x[i] = __measure_power(5);
105
106	*freq = (*freq + intel_rps_read_actual_frequency(rps)) / 2;
107
108	/* A simple triangle filter for better result stability */
109	sort(x, 5, sizeof(*x), cmp_u64, NULL);
110	return div_u64(x[1] + 2 * x[2] + x[3], 4);
111}
112
113static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power)
114{
115	int err = 0;
116
117	err = slpc_set_freq(gt, *freq);
118	if (err)
119		return err;
120	*freq = intel_rps_read_actual_frequency(&gt->rps);
121	*power = slpc_measure_power(&gt->rps, freq);
122
123	return err;
124}
125
126static int vary_max_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
127			 u32 *max_act_freq)
128{
129	u32 step, max_freq, req_freq;
130	u32 act_freq;
131	int err = 0;
132
133	/* Go from max to min in 5 steps */
134	step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
135	*max_act_freq = slpc->min_freq;
136	for (max_freq = slpc->rp0_freq; max_freq > slpc->min_freq;
137				max_freq -= step) {
138		err = slpc_set_max_freq(slpc, max_freq);
139		if (err)
140			break;
141
142		req_freq = intel_rps_read_punit_req_frequency(rps);
143
144		/* GuC requests freq in multiples of 50/3 MHz */
145		if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
146			pr_err("SWReq is %d, should be at most %d\n", req_freq,
147			       max_freq + FREQUENCY_REQ_UNIT);
148			err = -EINVAL;
149		}
150
151		act_freq =  intel_rps_read_actual_frequency(rps);
152		if (act_freq > *max_act_freq)
153			*max_act_freq = act_freq;
154
155		if (err)
156			break;
157	}
158
159	return err;
160}
161
162static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
163			 u32 *max_act_freq)
164{
165	u32 step, min_freq, req_freq;
166	u32 act_freq;
167	int err = 0;
168
169	/* Go from min to max in 5 steps */
170	step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
171	*max_act_freq = slpc->min_freq;
172	for (min_freq = slpc->min_freq; min_freq < slpc->rp0_freq;
173				min_freq += step) {
174		err = slpc_set_min_freq(slpc, min_freq);
175		if (err)
176			break;
177
178		req_freq = intel_rps_read_punit_req_frequency(rps);
179
180		/* GuC requests freq in multiples of 50/3 MHz */
181		if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
182			pr_err("SWReq is %d, should be at least %d\n", req_freq,
183			       min_freq - FREQUENCY_REQ_UNIT);
184			err = -EINVAL;
185		}
186
187		act_freq =  intel_rps_read_actual_frequency(rps);
188		if (act_freq > *max_act_freq)
189			*max_act_freq = act_freq;
190
191		if (err)
192			break;
193	}
194
195	return err;
196}
197
198static int slpc_power(struct intel_gt *gt, struct intel_engine_cs *engine)
199{
200	struct intel_guc_slpc *slpc = &gt_to_guc(gt)->slpc;
201	struct {
202		u64 power;
203		int freq;
204	} min, max;
205	int err = 0;
206
207	/*
208	 * Our fundamental assumption is that running at lower frequency
209	 * actually saves power. Let's see if our RAPL measurement supports
210	 * that theory.
211	 */
212	if (!librapl_supported(gt->i915))
213		return 0;
214
215	min.freq = slpc->min_freq;
216	err = measure_power_at_freq(gt, &min.freq, &min.power);
217
218	if (err)
219		return err;
220
221	max.freq = slpc->rp0_freq;
222	err = measure_power_at_freq(gt, &max.freq, &max.power);
223
224	if (err)
225		return err;
226
227	pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
228		engine->name,
229		min.power, min.freq,
230		max.power, max.freq);
231
232	if (10 * min.freq >= 9 * max.freq) {
233		pr_notice("Could not control frequency, ran at [%uMHz, %uMhz]\n",
234			  min.freq, max.freq);
235	}
236
237	if (11 * min.power > 10 * max.power) {
238		pr_err("%s: did not conserve power when setting lower frequency!\n",
239		       engine->name);
240		err = -EINVAL;
241	}
242
243	/* Restore min/max frequencies */
244	slpc_set_max_freq(slpc, slpc->rp0_freq);
245	slpc_set_min_freq(slpc, slpc->min_freq);
246
247	return err;
248}
249
250static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, u32 *max_act_freq)
251{
252	struct intel_gt *gt = rps_to_gt(rps);
253	u32 perf_limit_reasons;
254	int err = 0;
255
256	err = slpc_set_min_freq(slpc, slpc->rp0_freq);
257	if (err)
258		return err;
259
260	*max_act_freq =  intel_rps_read_actual_frequency(rps);
261	if (*max_act_freq != slpc->rp0_freq) {
262		/* Check if there was some throttling by pcode */
263		perf_limit_reasons = intel_uncore_read(gt->uncore,
264						       intel_gt_perf_limit_reasons_reg(gt));
265
266		/* If not, this is an error */
267		if (!(perf_limit_reasons & GT0_PERF_LIMIT_REASONS_MASK)) {
268			pr_err("Pcode did not grant max freq\n");
269			err = -EINVAL;
270		} else {
271			pr_info("Pcode throttled frequency 0x%x\n", perf_limit_reasons);
272		}
273	}
274
275	return err;
276}
277
278static int run_test(struct intel_gt *gt, int test_type)
279{
280	struct intel_guc_slpc *slpc = &gt_to_guc(gt)->slpc;
281	struct intel_rps *rps = &gt->rps;
282	struct intel_engine_cs *engine;
283	enum intel_engine_id id;
284	intel_wakeref_t wakeref;
285	struct igt_spinner spin;
286	u32 slpc_min_freq, slpc_max_freq;
287	int err = 0;
288
289	if (!intel_uc_uses_guc_slpc(&gt->uc))
290		return 0;
291
292	if (slpc->min_freq == slpc->rp0_freq) {
293		pr_err("Min/Max are fused to the same value\n");
294		return -EINVAL;
295	}
296
297	if (igt_spinner_init(&spin, gt))
298		return -ENOMEM;
299
300	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
301		pr_err("Could not get SLPC max freq\n");
302		return -EIO;
303	}
304
305	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
306		pr_err("Could not get SLPC min freq\n");
307		return -EIO;
308	}
309
310	/*
311	 * Set min frequency to RPn so that we can test the whole
312	 * range of RPn-RP0.
313	 */
314	err = slpc_set_min_freq(slpc, slpc->min_freq);
315	if (err) {
316		pr_err("Unable to update min freq!");
317		return err;
318	}
319
320	/*
321	 * Turn off efficient frequency so RPn/RP0 ranges are obeyed.
322	 */
323	err = intel_guc_slpc_set_ignore_eff_freq(slpc, true);
324	if (err) {
325		pr_err("Unable to turn off efficient freq!");
326		return err;
327	}
328
329	intel_gt_pm_wait_for_idle(gt);
330	wakeref = intel_gt_pm_get(gt);
331	for_each_engine(engine, gt, id) {
332		struct i915_request *rq;
333		u32 max_act_freq;
334
335		if (!intel_engine_can_store_dword(engine))
336			continue;
337
338		st_engine_heartbeat_disable(engine);
339
340		rq = igt_spinner_create_request(&spin,
341						engine->kernel_context,
342						MI_NOOP);
343		if (IS_ERR(rq)) {
344			err = PTR_ERR(rq);
345			st_engine_heartbeat_enable(engine);
346			break;
347		}
348
349		i915_request_add(rq);
350
351		if (!igt_wait_for_spinner(&spin, rq)) {
352			pr_err("%s: Spinner did not start\n",
353			       engine->name);
354			igt_spinner_end(&spin);
355			st_engine_heartbeat_enable(engine);
356			intel_gt_set_wedged(engine->gt);
357			err = -EIO;
358			break;
359		}
360
361		switch (test_type) {
362		case VARY_MIN:
363			err = vary_min_freq(slpc, rps, &max_act_freq);
364			break;
365
366		case VARY_MAX:
367			err = vary_max_freq(slpc, rps, &max_act_freq);
368			break;
369
370		case MAX_GRANTED:
371		case TILE_INTERACTION:
372			/* Media engines have a different RP0 */
373			if (gt->type != GT_MEDIA && (engine->class == VIDEO_DECODE_CLASS ||
374						     engine->class == VIDEO_ENHANCEMENT_CLASS)) {
375				igt_spinner_end(&spin);
376				st_engine_heartbeat_enable(engine);
377				err = 0;
378				continue;
379			}
380
381			err = max_granted_freq(slpc, rps, &max_act_freq);
382			break;
383
384		case SLPC_POWER:
385			err = slpc_power(gt, engine);
386			break;
387		}
388
389		if (test_type != SLPC_POWER) {
390			pr_info("Max actual frequency for %s was %d\n",
391				engine->name, max_act_freq);
392
393			/* Actual frequency should rise above min */
394			if (max_act_freq <= slpc->min_freq) {
395				pr_err("Actual freq did not rise above min\n");
396				pr_err("Perf Limit Reasons: 0x%x\n",
397				       intel_uncore_read(gt->uncore,
398							 intel_gt_perf_limit_reasons_reg(gt)));
399				err = -EINVAL;
400			}
401		}
402
403		igt_spinner_end(&spin);
404		st_engine_heartbeat_enable(engine);
405
406		if (err)
407			break;
408	}
409
410	/* Restore min/max/efficient frequencies */
411	err = slpc_restore_freq(slpc, slpc_min_freq, slpc_max_freq);
412
413	if (igt_flush_test(gt->i915))
414		err = -EIO;
415
416	intel_gt_pm_put(gt, wakeref);
417	igt_spinner_fini(&spin);
418	intel_gt_pm_wait_for_idle(gt);
419
420	return err;
421}
422
423static int live_slpc_vary_min(void *arg)
424{
425	struct drm_i915_private *i915 = arg;
426	struct intel_gt *gt;
427	unsigned int i;
428	int ret;
429
430	for_each_gt(gt, i915, i) {
431		ret = run_test(gt, VARY_MIN);
432		if (ret)
433			return ret;
434	}
435
436	return ret;
437}
438
439static int live_slpc_vary_max(void *arg)
440{
441	struct drm_i915_private *i915 = arg;
442	struct intel_gt *gt;
443	unsigned int i;
444	int ret;
445
446	for_each_gt(gt, i915, i) {
447		ret = run_test(gt, VARY_MAX);
448		if (ret)
449			return ret;
450	}
451
452	return ret;
453}
454
455/* check if pcode can grant RP0 */
456static int live_slpc_max_granted(void *arg)
457{
458	struct drm_i915_private *i915 = arg;
459	struct intel_gt *gt;
460	unsigned int i;
461	int ret;
462
463	for_each_gt(gt, i915, i) {
464		ret = run_test(gt, MAX_GRANTED);
465		if (ret)
466			return ret;
467	}
468
469	return ret;
470}
471
472static int live_slpc_power(void *arg)
473{
474	struct drm_i915_private *i915 = arg;
475	struct intel_gt *gt;
476	unsigned int i;
477	int ret;
478
479	for_each_gt(gt, i915, i) {
480		ret = run_test(gt, SLPC_POWER);
481		if (ret)
482			return ret;
483	}
484
485	return ret;
486}
487
488static void slpc_spinner_thread(struct kthread_work *work)
489{
490	struct slpc_thread *thread = container_of(work, typeof(*thread), work);
491
492	thread->result = run_test(thread->gt, TILE_INTERACTION);
493}
494
495static int live_slpc_tile_interaction(void *arg)
496{
497	struct drm_i915_private *i915 = arg;
498	struct intel_gt *gt;
499	struct slpc_thread *threads;
500	int i = 0, ret = 0;
501
502	threads = kcalloc(I915_MAX_GT, sizeof(*threads), GFP_KERNEL);
503	if (!threads)
504		return -ENOMEM;
505
506	for_each_gt(gt, i915, i) {
507		threads[i].worker = kthread_run_worker(0, "igt/slpc_parallel:%d", gt->info.id);
508
509		if (IS_ERR(threads[i].worker)) {
510			ret = PTR_ERR(threads[i].worker);
511			break;
512		}
513
514		threads[i].gt = gt;
515		kthread_init_work(&threads[i].work, slpc_spinner_thread);
516		kthread_queue_work(threads[i].worker, &threads[i].work);
517	}
518
519	for_each_gt(gt, i915, i) {
520		int status;
521
522		if (IS_ERR_OR_NULL(threads[i].worker))
523			continue;
524
525		kthread_flush_work(&threads[i].work);
526		status = READ_ONCE(threads[i].result);
527		if (status && !ret) {
528			pr_err("%s GT %d failed ", __func__, gt->info.id);
529			ret = status;
530		}
531		kthread_destroy_worker(threads[i].worker);
532	}
533
534	kfree(threads);
535	return ret;
536}
537
538int intel_slpc_live_selftests(struct drm_i915_private *i915)
539{
540	static const struct i915_subtest tests[] = {
541		SUBTEST(live_slpc_vary_max),
542		SUBTEST(live_slpc_vary_min),
543		SUBTEST(live_slpc_max_granted),
544		SUBTEST(live_slpc_power),
545		SUBTEST(live_slpc_tile_interaction),
546	};
547
548	struct intel_gt *gt;
549	unsigned int i;
550
551	for_each_gt(gt, i915, i) {
552		if (intel_gt_is_wedged(gt))
553			return 0;
554	}
555
556	return i915_live_subtests(tests, i915);
557}
~/ Read-only file preview.