Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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->uc.guc.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 u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power)
 74{
 75	int err = 0;
 76
 77	err = slpc_set_freq(gt, *freq);
 78	if (err)
 79		return err;
 80	*freq = intel_rps_read_actual_frequency(&gt->rps);
 81	*power = measure_power(&gt->rps, freq);
 82
 83	return err;
 84}
 85
 86static int vary_max_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
 87			 u32 *max_act_freq)
 88{
 89	u32 step, max_freq, req_freq;
 90	u32 act_freq;
 91	int err = 0;
 92
 93	/* Go from max to min in 5 steps */
 94	step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
 95	*max_act_freq = slpc->min_freq;
 96	for (max_freq = slpc->rp0_freq; max_freq > slpc->min_freq;
 97				max_freq -= step) {
 98		err = slpc_set_max_freq(slpc, max_freq);
 99		if (err)
100			break;
101
102		req_freq = intel_rps_read_punit_req_frequency(rps);
103
104		/* GuC requests freq in multiples of 50/3 MHz */
105		if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) {
106			pr_err("SWReq is %d, should be at most %d\n", req_freq,
107			       max_freq + FREQUENCY_REQ_UNIT);
108			err = -EINVAL;
109		}
110
111		act_freq =  intel_rps_read_actual_frequency(rps);
112		if (act_freq > *max_act_freq)
113			*max_act_freq = act_freq;
114
115		if (err)
116			break;
117	}
118
119	return err;
120}
121
122static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
123			 u32 *max_act_freq)
124{
125	u32 step, min_freq, req_freq;
126	u32 act_freq;
127	int err = 0;
128
129	/* Go from min to max in 5 steps */
130	step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS;
131	*max_act_freq = slpc->min_freq;
132	for (min_freq = slpc->min_freq; min_freq < slpc->rp0_freq;
133				min_freq += step) {
134		err = slpc_set_min_freq(slpc, min_freq);
135		if (err)
136			break;
137
138		req_freq = intel_rps_read_punit_req_frequency(rps);
139
140		/* GuC requests freq in multiples of 50/3 MHz */
141		if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) {
142			pr_err("SWReq is %d, should be at least %d\n", req_freq,
143			       min_freq - FREQUENCY_REQ_UNIT);
144			err = -EINVAL;
145		}
146
147		act_freq =  intel_rps_read_actual_frequency(rps);
148		if (act_freq > *max_act_freq)
149			*max_act_freq = act_freq;
150
151		if (err)
152			break;
153	}
154
155	return err;
156}
157
158static int slpc_power(struct intel_gt *gt, struct intel_engine_cs *engine)
159{
160	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
161	struct {
162		u64 power;
163		int freq;
164	} min, max;
165	int err = 0;
166
167	/*
168	 * Our fundamental assumption is that running at lower frequency
169	 * actually saves power. Let's see if our RAPL measurement supports
170	 * that theory.
171	 */
172	if (!librapl_supported(gt->i915))
173		return 0;
174
175	min.freq = slpc->min_freq;
176	err = measure_power_at_freq(gt, &min.freq, &min.power);
177
178	if (err)
179		return err;
180
181	max.freq = slpc->rp0_freq;
182	err = measure_power_at_freq(gt, &max.freq, &max.power);
183
184	if (err)
185		return err;
186
187	pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
188		engine->name,
189		min.power, min.freq,
190		max.power, max.freq);
191
192	if (10 * min.freq >= 9 * max.freq) {
193		pr_notice("Could not control frequency, ran at [%uMHz, %uMhz]\n",
194			  min.freq, max.freq);
195	}
196
197	if (11 * min.power > 10 * max.power) {
198		pr_err("%s: did not conserve power when setting lower frequency!\n",
199		       engine->name);
200		err = -EINVAL;
201	}
202
203	/* Restore min/max frequencies */
204	slpc_set_max_freq(slpc, slpc->rp0_freq);
205	slpc_set_min_freq(slpc, slpc->min_freq);
206
207	return err;
208}
209
210static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, u32 *max_act_freq)
211{
212	struct intel_gt *gt = rps_to_gt(rps);
213	u32 perf_limit_reasons;
214	int err = 0;
215
216	err = slpc_set_min_freq(slpc, slpc->rp0_freq);
217	if (err)
218		return err;
219
220	*max_act_freq =  intel_rps_read_actual_frequency(rps);
221	if (*max_act_freq != slpc->rp0_freq) {
222		/* Check if there was some throttling by pcode */
223		perf_limit_reasons = intel_uncore_read(gt->uncore,
224						       intel_gt_perf_limit_reasons_reg(gt));
225
226		/* If not, this is an error */
227		if (!(perf_limit_reasons & GT0_PERF_LIMIT_REASONS_MASK)) {
228			pr_err("Pcode did not grant max freq\n");
229			err = -EINVAL;
230		} else {
231			pr_info("Pcode throttled frequency 0x%x\n", perf_limit_reasons);
232		}
233	}
234
235	return err;
236}
237
238static int run_test(struct intel_gt *gt, int test_type)
239{
240	struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
241	struct intel_rps *rps = &gt->rps;
242	struct intel_engine_cs *engine;
243	enum intel_engine_id id;
244	struct igt_spinner spin;
245	u32 slpc_min_freq, slpc_max_freq;
246	int err = 0;
247
248	if (!intel_uc_uses_guc_slpc(&gt->uc))
249		return 0;
250
251	if (slpc->min_freq == slpc->rp0_freq) {
252		pr_err("Min/Max are fused to the same value\n");
253		return -EINVAL;
254	}
255
256	if (igt_spinner_init(&spin, gt))
257		return -ENOMEM;
258
259	if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) {
260		pr_err("Could not get SLPC max freq\n");
261		return -EIO;
262	}
263
264	if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) {
265		pr_err("Could not get SLPC min freq\n");
266		return -EIO;
267	}
268
269	/*
270	 * Set min frequency to RPn so that we can test the whole
271	 * range of RPn-RP0. This also turns off efficient freq
272	 * usage and makes results more predictable.
273	 */
274	err = slpc_set_min_freq(slpc, slpc->min_freq);
275	if (err) {
276		pr_err("Unable to update min freq!");
277		return err;
278	}
279
280	intel_gt_pm_wait_for_idle(gt);
281	intel_gt_pm_get(gt);
282	for_each_engine(engine, gt, id) {
283		struct i915_request *rq;
284		u32 max_act_freq;
285
286		if (!intel_engine_can_store_dword(engine))
287			continue;
288
289		st_engine_heartbeat_disable(engine);
290
291		rq = igt_spinner_create_request(&spin,
292						engine->kernel_context,
293						MI_NOOP);
294		if (IS_ERR(rq)) {
295			err = PTR_ERR(rq);
296			st_engine_heartbeat_enable(engine);
297			break;
298		}
299
300		i915_request_add(rq);
301
302		if (!igt_wait_for_spinner(&spin, rq)) {
303			pr_err("%s: Spinner did not start\n",
304			       engine->name);
305			igt_spinner_end(&spin);
306			st_engine_heartbeat_enable(engine);
307			intel_gt_set_wedged(engine->gt);
308			err = -EIO;
309			break;
310		}
311
312		switch (test_type) {
313		case VARY_MIN:
314			err = vary_min_freq(slpc, rps, &max_act_freq);
315			break;
316
317		case VARY_MAX:
318			err = vary_max_freq(slpc, rps, &max_act_freq);
319			break;
320
321		case MAX_GRANTED:
322		case TILE_INTERACTION:
323			/* Media engines have a different RP0 */
324			if (gt->type != GT_MEDIA && (engine->class == VIDEO_DECODE_CLASS ||
325						     engine->class == VIDEO_ENHANCEMENT_CLASS)) {
326				igt_spinner_end(&spin);
327				st_engine_heartbeat_enable(engine);
328				err = 0;
329				continue;
330			}
331
332			err = max_granted_freq(slpc, rps, &max_act_freq);
333			break;
334
335		case SLPC_POWER:
336			err = slpc_power(gt, engine);
337			break;
338		}
339
340		if (test_type != SLPC_POWER) {
341			pr_info("Max actual frequency for %s was %d\n",
342				engine->name, max_act_freq);
343
344			/* Actual frequency should rise above min */
345			if (max_act_freq <= slpc->min_freq) {
346				pr_err("Actual freq did not rise above min\n");
347				pr_err("Perf Limit Reasons: 0x%x\n",
348				       intel_uncore_read(gt->uncore,
349							 intel_gt_perf_limit_reasons_reg(gt)));
350				err = -EINVAL;
351			}
352		}
353
354		igt_spinner_end(&spin);
355		st_engine_heartbeat_enable(engine);
356
357		if (err)
358			break;
359	}
360
361	/* Restore min/max frequencies */
362	slpc_set_max_freq(slpc, slpc_max_freq);
363	slpc_set_min_freq(slpc, slpc_min_freq);
364
365	if (igt_flush_test(gt->i915))
366		err = -EIO;
367
368	intel_gt_pm_put(gt);
369	igt_spinner_fini(&spin);
370	intel_gt_pm_wait_for_idle(gt);
371
372	return err;
373}
374
375static int live_slpc_vary_min(void *arg)
376{
377	struct drm_i915_private *i915 = arg;
378	struct intel_gt *gt;
379	unsigned int i;
380	int ret;
381
382	for_each_gt(gt, i915, i) {
383		ret = run_test(gt, VARY_MIN);
384		if (ret)
385			return ret;
386	}
387
388	return ret;
389}
390
391static int live_slpc_vary_max(void *arg)
392{
393	struct drm_i915_private *i915 = arg;
394	struct intel_gt *gt;
395	unsigned int i;
396	int ret;
397
398	for_each_gt(gt, i915, i) {
399		ret = run_test(gt, VARY_MAX);
400		if (ret)
401			return ret;
402	}
403
404	return ret;
405}
406
407/* check if pcode can grant RP0 */
408static int live_slpc_max_granted(void *arg)
409{
410	struct drm_i915_private *i915 = arg;
411	struct intel_gt *gt;
412	unsigned int i;
413	int ret;
414
415	for_each_gt(gt, i915, i) {
416		ret = run_test(gt, MAX_GRANTED);
417		if (ret)
418			return ret;
419	}
420
421	return ret;
422}
423
424static int live_slpc_power(void *arg)
425{
426	struct drm_i915_private *i915 = arg;
427	struct intel_gt *gt;
428	unsigned int i;
429	int ret;
430
431	for_each_gt(gt, i915, i) {
432		ret = run_test(gt, SLPC_POWER);
433		if (ret)
434			return ret;
435	}
436
437	return ret;
438}
439
440static void slpc_spinner_thread(struct kthread_work *work)
441{
442	struct slpc_thread *thread = container_of(work, typeof(*thread), work);
443
444	thread->result = run_test(thread->gt, TILE_INTERACTION);
445}
446
447static int live_slpc_tile_interaction(void *arg)
448{
449	struct drm_i915_private *i915 = arg;
450	struct intel_gt *gt;
451	struct slpc_thread *threads;
452	int i = 0, ret = 0;
453
454	threads = kcalloc(I915_MAX_GT, sizeof(*threads), GFP_KERNEL);
455	if (!threads)
456		return -ENOMEM;
457
458	for_each_gt(gt, i915, i) {
459		threads[i].worker = kthread_create_worker(0, "igt/slpc_parallel:%d", gt->info.id);
460
461		if (IS_ERR(threads[i].worker)) {
462			ret = PTR_ERR(threads[i].worker);
463			break;
464		}
465
466		threads[i].gt = gt;
467		kthread_init_work(&threads[i].work, slpc_spinner_thread);
468		kthread_queue_work(threads[i].worker, &threads[i].work);
469	}
470
471	for_each_gt(gt, i915, i) {
472		int status;
473
474		if (IS_ERR_OR_NULL(threads[i].worker))
475			continue;
476
477		kthread_flush_work(&threads[i].work);
478		status = READ_ONCE(threads[i].result);
479		if (status && !ret) {
480			pr_err("%s GT %d failed ", __func__, gt->info.id);
481			ret = status;
482		}
483		kthread_destroy_worker(threads[i].worker);
484	}
485
486	kfree(threads);
487	return ret;
488}
489
490int intel_slpc_live_selftests(struct drm_i915_private *i915)
491{
492	static const struct i915_subtest tests[] = {
493		SUBTEST(live_slpc_vary_max),
494		SUBTEST(live_slpc_vary_min),
495		SUBTEST(live_slpc_max_granted),
496		SUBTEST(live_slpc_power),
497		SUBTEST(live_slpc_tile_interaction),
498	};
499
500	struct intel_gt *gt;
501	unsigned int i;
502
503	for_each_gt(gt, i915, i) {
504		if (intel_gt_is_wedged(gt))
505			return 0;
506	}
507
508	return i915_live_subtests(tests, i915);
509}