xref: /linux/drivers/crypto/intel/qat/qat_common/adf_tl_debugfs.c (revision 6093a688a07da07808f0122f9aa2a3eed250d853)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2023 Intel Corporation. */
3 #define dev_fmt(fmt) "Telemetry debugfs: " fmt
4 
5 #include <linux/atomic.h>
6 #include <linux/debugfs.h>
7 #include <linux/dev_printk.h>
8 #include <linux/dcache.h>
9 #include <linux/file.h>
10 #include <linux/kernel.h>
11 #include <linux/math64.h>
12 #include <linux/mutex.h>
13 #include <linux/seq_file.h>
14 #include <linux/slab.h>
15 #include <linux/units.h>
16 
17 #include "adf_accel_devices.h"
18 #include "adf_cfg_strings.h"
19 #include "adf_telemetry.h"
20 #include "adf_tl_debugfs.h"
21 
22 #define TL_VALUE_MIN_PADDING	20
23 #define TL_KEY_MIN_PADDING	23
24 #define TL_RP_SRV_UNKNOWN	"Unknown"
25 
26 static int tl_collect_values_u32(struct adf_telemetry *telemetry,
27 				 size_t counter_offset, u64 *arr)
28 {
29 	unsigned int samples, hb_idx, i;
30 	u32 *regs_hist_buff;
31 	u32 counter_val;
32 
33 	samples = min(telemetry->msg_cnt, telemetry->hbuffs);
34 	hb_idx = telemetry->hb_num + telemetry->hbuffs - samples;
35 
36 	mutex_lock(&telemetry->regs_hist_lock);
37 
38 	for (i = 0; i < samples; i++) {
39 		regs_hist_buff = telemetry->regs_hist_buff[hb_idx % telemetry->hbuffs];
40 		counter_val = regs_hist_buff[counter_offset / sizeof(counter_val)];
41 		arr[i] = counter_val;
42 		hb_idx++;
43 	}
44 
45 	mutex_unlock(&telemetry->regs_hist_lock);
46 
47 	return samples;
48 }
49 
50 static int tl_collect_values_u64(struct adf_telemetry *telemetry,
51 				 size_t counter_offset, u64 *arr)
52 {
53 	unsigned int samples, hb_idx, i;
54 	u64 *regs_hist_buff;
55 	u64 counter_val;
56 
57 	samples = min(telemetry->msg_cnt, telemetry->hbuffs);
58 	hb_idx = telemetry->hb_num + telemetry->hbuffs - samples;
59 
60 	mutex_lock(&telemetry->regs_hist_lock);
61 
62 	for (i = 0; i < samples; i++) {
63 		regs_hist_buff = telemetry->regs_hist_buff[hb_idx % telemetry->hbuffs];
64 		counter_val = regs_hist_buff[counter_offset / sizeof(counter_val)];
65 		arr[i] = counter_val;
66 		hb_idx++;
67 	}
68 
69 	mutex_unlock(&telemetry->regs_hist_lock);
70 
71 	return samples;
72 }
73 
74 /**
75  * avg_array() - Return average of values within an array.
76  * @array: Array of values.
77  * @len: Number of elements.
78  *
79  * This algorithm computes average of an array without running into overflow.
80  *
81  * Return: average of values.
82  */
83 #define avg_array(array, len) (				\
84 {							\
85 	typeof(&(array)[0]) _array = (array);		\
86 	__unqual_scalar_typeof(_array[0]) _x = 0;	\
87 	__unqual_scalar_typeof(_array[0]) _y = 0;	\
88 	__unqual_scalar_typeof(_array[0]) _a, _b;	\
89 	typeof(len) _len = (len);			\
90 	size_t _i;					\
91 							\
92 	for (_i = 0; _i < _len; _i++) {			\
93 		_a = _array[_i];			\
94 		_b = do_div(_a, _len);			\
95 		_x += _a;				\
96 		if (_y >= _len - _b) {			\
97 			_x++;				\
98 			_y -= _len - _b;		\
99 		} else {				\
100 			_y += _b;			\
101 		}					\
102 	}						\
103 	do_div(_y, _len);				\
104 	(_x + _y);					\
105 })
106 
107 /* Calculation function for simple counter. */
108 static int tl_calc_count(struct adf_telemetry *telemetry,
109 			 const struct adf_tl_dbg_counter *ctr,
110 			 struct adf_tl_dbg_aggr_values *vals)
111 {
112 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(telemetry->accel_dev);
113 	u64 *hist_vals;
114 	int sample_cnt;
115 	int ret = 0;
116 
117 	hist_vals = kmalloc_array(tl_data->num_hbuff, sizeof(*hist_vals),
118 				  GFP_KERNEL);
119 	if (!hist_vals)
120 		return -ENOMEM;
121 
122 	memset(vals, 0, sizeof(*vals));
123 	sample_cnt = tl_collect_values_u32(telemetry, ctr->offset1, hist_vals);
124 	if (!sample_cnt)
125 		goto out_free_hist_vals;
126 
127 	vals->curr = hist_vals[sample_cnt - 1];
128 	vals->min = min_array(hist_vals, sample_cnt);
129 	vals->max = max_array(hist_vals, sample_cnt);
130 	vals->avg = avg_array(hist_vals, sample_cnt);
131 
132 out_free_hist_vals:
133 	kfree(hist_vals);
134 	return ret;
135 }
136 
137 /* Convert CPP bus cycles to ns. */
138 static int tl_cycles_to_ns(struct adf_telemetry *telemetry,
139 			   const struct adf_tl_dbg_counter *ctr,
140 			   struct adf_tl_dbg_aggr_values *vals)
141 {
142 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(telemetry->accel_dev);
143 	u8 cpp_ns_per_cycle = tl_data->cpp_ns_per_cycle;
144 	int ret;
145 
146 	ret = tl_calc_count(telemetry, ctr, vals);
147 	if (ret)
148 		return ret;
149 
150 	vals->curr *= cpp_ns_per_cycle;
151 	vals->min *= cpp_ns_per_cycle;
152 	vals->max *= cpp_ns_per_cycle;
153 	vals->avg *= cpp_ns_per_cycle;
154 
155 	return 0;
156 }
157 
158 /*
159  * Compute latency cumulative average with division of accumulated value
160  * by sample count. Returned value is in ns.
161  */
162 static int tl_lat_acc_avg(struct adf_telemetry *telemetry,
163 			  const struct adf_tl_dbg_counter *ctr,
164 			  struct adf_tl_dbg_aggr_values *vals)
165 {
166 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(telemetry->accel_dev);
167 	u8 cpp_ns_per_cycle = tl_data->cpp_ns_per_cycle;
168 	u8 num_hbuff = tl_data->num_hbuff;
169 	int sample_cnt, i;
170 	u64 *hist_vals;
171 	u64 *hist_cnt;
172 	int ret = 0;
173 
174 	hist_vals = kmalloc_array(num_hbuff, sizeof(*hist_vals), GFP_KERNEL);
175 	if (!hist_vals)
176 		return -ENOMEM;
177 
178 	hist_cnt = kmalloc_array(num_hbuff, sizeof(*hist_cnt), GFP_KERNEL);
179 	if (!hist_cnt) {
180 		ret = -ENOMEM;
181 		goto out_free_hist_vals;
182 	}
183 
184 	memset(vals, 0, sizeof(*vals));
185 	sample_cnt = tl_collect_values_u64(telemetry, ctr->offset1, hist_vals);
186 	if (!sample_cnt)
187 		goto out_free_hist_cnt;
188 
189 	tl_collect_values_u32(telemetry, ctr->offset2, hist_cnt);
190 
191 	for (i = 0; i < sample_cnt; i++) {
192 		/* Avoid division by 0 if count is 0. */
193 		if (hist_cnt[i])
194 			hist_vals[i] = div_u64(hist_vals[i] * cpp_ns_per_cycle,
195 					       hist_cnt[i]);
196 		else
197 			hist_vals[i] = 0;
198 	}
199 
200 	vals->curr = hist_vals[sample_cnt - 1];
201 	vals->min = min_array(hist_vals, sample_cnt);
202 	vals->max = max_array(hist_vals, sample_cnt);
203 	vals->avg = avg_array(hist_vals, sample_cnt);
204 
205 out_free_hist_cnt:
206 	kfree(hist_cnt);
207 out_free_hist_vals:
208 	kfree(hist_vals);
209 	return ret;
210 }
211 
212 /* Convert HW raw bandwidth units to Mbps. */
213 static int tl_bw_hw_units_to_mbps(struct adf_telemetry *telemetry,
214 				  const struct adf_tl_dbg_counter *ctr,
215 				  struct adf_tl_dbg_aggr_values *vals)
216 {
217 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(telemetry->accel_dev);
218 	u16 bw_hw_2_bits = tl_data->bw_units_to_bytes * BITS_PER_BYTE;
219 	u64 *hist_vals;
220 	int sample_cnt;
221 	int ret = 0;
222 
223 	hist_vals = kmalloc_array(tl_data->num_hbuff, sizeof(*hist_vals),
224 				  GFP_KERNEL);
225 	if (!hist_vals)
226 		return -ENOMEM;
227 
228 	memset(vals, 0, sizeof(*vals));
229 	sample_cnt = tl_collect_values_u32(telemetry, ctr->offset1, hist_vals);
230 	if (!sample_cnt)
231 		goto out_free_hist_vals;
232 
233 	vals->curr = div_u64(hist_vals[sample_cnt - 1] * bw_hw_2_bits, MEGA);
234 	vals->min = div_u64(min_array(hist_vals, sample_cnt) * bw_hw_2_bits, MEGA);
235 	vals->max = div_u64(max_array(hist_vals, sample_cnt) * bw_hw_2_bits, MEGA);
236 	vals->avg = div_u64(avg_array(hist_vals, sample_cnt) * bw_hw_2_bits, MEGA);
237 
238 out_free_hist_vals:
239 	kfree(hist_vals);
240 	return ret;
241 }
242 
243 static void tl_seq_printf_counter(struct adf_telemetry *telemetry,
244 				  struct seq_file *s, const char *name,
245 				  struct adf_tl_dbg_aggr_values *vals)
246 {
247 	seq_printf(s, "%-*s", TL_KEY_MIN_PADDING, name);
248 	seq_printf(s, "%*llu", TL_VALUE_MIN_PADDING, vals->curr);
249 	if (atomic_read(&telemetry->state) > 1) {
250 		seq_printf(s, "%*llu", TL_VALUE_MIN_PADDING, vals->min);
251 		seq_printf(s, "%*llu", TL_VALUE_MIN_PADDING, vals->max);
252 		seq_printf(s, "%*llu", TL_VALUE_MIN_PADDING, vals->avg);
253 	}
254 	seq_puts(s, "\n");
255 }
256 
257 static int tl_calc_and_print_counter(struct adf_telemetry *telemetry,
258 				     struct seq_file *s,
259 				     const struct adf_tl_dbg_counter *ctr,
260 				     const char *name)
261 {
262 	const char *counter_name = name ? name : ctr->name;
263 	enum adf_tl_counter_type type = ctr->type;
264 	struct adf_tl_dbg_aggr_values vals;
265 	int ret;
266 
267 	switch (type) {
268 	case ADF_TL_SIMPLE_COUNT:
269 		ret = tl_calc_count(telemetry, ctr, &vals);
270 		break;
271 	case ADF_TL_COUNTER_NS:
272 		ret = tl_cycles_to_ns(telemetry, ctr, &vals);
273 		break;
274 	case ADF_TL_COUNTER_NS_AVG:
275 		ret = tl_lat_acc_avg(telemetry, ctr, &vals);
276 		break;
277 	case ADF_TL_COUNTER_MBPS:
278 		ret = tl_bw_hw_units_to_mbps(telemetry, ctr, &vals);
279 		break;
280 	default:
281 		return -EINVAL;
282 	}
283 
284 	if (ret)
285 		return ret;
286 
287 	tl_seq_printf_counter(telemetry, s, counter_name, &vals);
288 
289 	return 0;
290 }
291 
292 static int tl_print_sl_counter(struct adf_telemetry *telemetry,
293 			       const struct adf_tl_dbg_counter *ctr,
294 			       struct seq_file *s, u8 cnt_id)
295 {
296 	size_t sl_regs_sz = GET_TL_DATA(telemetry->accel_dev).slice_reg_sz;
297 	struct adf_tl_dbg_counter slice_ctr;
298 	size_t offset_inc = cnt_id * sl_regs_sz;
299 	char cnt_name[MAX_COUNT_NAME_SIZE];
300 
301 	snprintf(cnt_name, MAX_COUNT_NAME_SIZE, "%s%d", ctr->name, cnt_id);
302 	slice_ctr = *ctr;
303 	slice_ctr.offset1 += offset_inc;
304 
305 	return tl_calc_and_print_counter(telemetry, s, &slice_ctr, cnt_name);
306 }
307 
308 static int tl_calc_and_print_sl_counters(struct adf_accel_dev *accel_dev,
309 					 struct seq_file *s, u8 cnt_type, u8 cnt_id)
310 {
311 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
312 	struct adf_telemetry *telemetry = accel_dev->telemetry;
313 	const struct adf_tl_dbg_counter *sl_tl_util_counters;
314 	const struct adf_tl_dbg_counter *sl_tl_exec_counters;
315 	const struct adf_tl_dbg_counter *ctr;
316 	int ret;
317 
318 	sl_tl_util_counters = tl_data->sl_util_counters;
319 	sl_tl_exec_counters = tl_data->sl_exec_counters;
320 
321 	ctr = &sl_tl_util_counters[cnt_type];
322 
323 	ret = tl_print_sl_counter(telemetry, ctr, s, cnt_id);
324 	if (ret) {
325 		dev_notice(&GET_DEV(accel_dev),
326 			   "invalid slice utilization counter type\n");
327 		return ret;
328 	}
329 
330 	ctr = &sl_tl_exec_counters[cnt_type];
331 
332 	ret = tl_print_sl_counter(telemetry, ctr, s, cnt_id);
333 	if (ret) {
334 		dev_notice(&GET_DEV(accel_dev),
335 			   "invalid slice execution counter type\n");
336 		return ret;
337 	}
338 
339 	return 0;
340 }
341 
342 static int tl_print_cmdq_counter(struct adf_telemetry *telemetry,
343 				 const struct adf_tl_dbg_counter *ctr,
344 				 struct seq_file *s, u8 cnt_id, u8 counter)
345 {
346 	size_t cmdq_regs_sz = GET_TL_DATA(telemetry->accel_dev).cmdq_reg_sz;
347 	size_t offset_inc = cnt_id * cmdq_regs_sz;
348 	struct adf_tl_dbg_counter slice_ctr;
349 	char cnt_name[MAX_COUNT_NAME_SIZE];
350 
351 	slice_ctr = *(ctr + counter);
352 	slice_ctr.offset1 += offset_inc;
353 	snprintf(cnt_name, MAX_COUNT_NAME_SIZE, "%s%d", slice_ctr.name, cnt_id);
354 
355 	return tl_calc_and_print_counter(telemetry, s, &slice_ctr, cnt_name);
356 }
357 
358 static int tl_calc_and_print_cmdq_counters(struct adf_accel_dev *accel_dev,
359 					   struct seq_file *s, u8 cnt_type,
360 					   u8 cnt_id)
361 {
362 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
363 	struct adf_telemetry *telemetry = accel_dev->telemetry;
364 	const struct adf_tl_dbg_counter **cmdq_tl_counters;
365 	const struct adf_tl_dbg_counter *ctr;
366 	u8 counter;
367 	int ret;
368 
369 	cmdq_tl_counters = tl_data->cmdq_counters;
370 	ctr = cmdq_tl_counters[cnt_type];
371 
372 	for (counter = 0; counter < tl_data->num_cmdq_counters; counter++) {
373 		ret = tl_print_cmdq_counter(telemetry, ctr, s, cnt_id, counter);
374 		if (ret) {
375 			dev_notice(&GET_DEV(accel_dev),
376 				   "invalid slice utilization counter type\n");
377 			return ret;
378 		}
379 	}
380 
381 	return 0;
382 }
383 
384 static void tl_print_msg_cnt(struct seq_file *s, u32 msg_cnt)
385 {
386 	seq_printf(s, "%-*s", TL_KEY_MIN_PADDING, SNAPSHOT_CNT_MSG);
387 	seq_printf(s, "%*u\n", TL_VALUE_MIN_PADDING, msg_cnt);
388 }
389 
390 static int tl_print_dev_data(struct adf_accel_dev *accel_dev,
391 			     struct seq_file *s)
392 {
393 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
394 	struct adf_telemetry *telemetry = accel_dev->telemetry;
395 	const struct adf_tl_dbg_counter *dev_tl_counters;
396 	u8 num_dev_counters = tl_data->num_dev_counters;
397 	u8 *cmdq_cnt = (u8 *)&telemetry->cmdq_cnt;
398 	u8 *sl_cnt = (u8 *)&telemetry->slice_cnt;
399 	const struct adf_tl_dbg_counter *ctr;
400 	unsigned int i;
401 	int ret;
402 	u8 j;
403 
404 	if (!atomic_read(&telemetry->state)) {
405 		dev_info(&GET_DEV(accel_dev), "not enabled\n");
406 		return -EPERM;
407 	}
408 
409 	dev_tl_counters = tl_data->dev_counters;
410 
411 	tl_print_msg_cnt(s, telemetry->msg_cnt);
412 
413 	/* Print device level telemetry. */
414 	for (i = 0; i < num_dev_counters; i++) {
415 		ctr = &dev_tl_counters[i];
416 		ret = tl_calc_and_print_counter(telemetry, s, ctr, NULL);
417 		if (ret) {
418 			dev_notice(&GET_DEV(accel_dev),
419 				   "invalid counter type\n");
420 			return ret;
421 		}
422 	}
423 
424 	/* Print per slice telemetry. */
425 	for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) {
426 		for (j = 0; j < sl_cnt[i]; j++) {
427 			ret = tl_calc_and_print_sl_counters(accel_dev, s, i, j);
428 			if (ret)
429 				return ret;
430 		}
431 	}
432 
433 	/* Print per command queue telemetry. */
434 	for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) {
435 		for (j = 0; j < cmdq_cnt[i]; j++) {
436 			ret = tl_calc_and_print_cmdq_counters(accel_dev, s, i, j);
437 			if (ret)
438 				return ret;
439 		}
440 	}
441 
442 	return 0;
443 }
444 
445 static int tl_dev_data_show(struct seq_file *s, void *unused)
446 {
447 	struct adf_accel_dev *accel_dev = s->private;
448 
449 	if (!accel_dev)
450 		return -EINVAL;
451 
452 	return tl_print_dev_data(accel_dev, s);
453 }
454 DEFINE_SHOW_ATTRIBUTE(tl_dev_data);
455 
456 static int tl_control_show(struct seq_file *s, void *unused)
457 {
458 	struct adf_accel_dev *accel_dev = s->private;
459 
460 	if (!accel_dev)
461 		return -EINVAL;
462 
463 	seq_printf(s, "%d\n", atomic_read(&accel_dev->telemetry->state));
464 
465 	return 0;
466 }
467 
468 static ssize_t tl_control_write(struct file *file, const char __user *userbuf,
469 				size_t count, loff_t *ppos)
470 {
471 	struct seq_file *seq_f = file->private_data;
472 	struct adf_accel_dev *accel_dev;
473 	struct adf_telemetry *telemetry;
474 	struct adf_tl_hw_data *tl_data;
475 	struct device *dev;
476 	u32 input;
477 	int ret;
478 
479 	accel_dev = seq_f->private;
480 	if (!accel_dev)
481 		return -EINVAL;
482 
483 	tl_data = &GET_TL_DATA(accel_dev);
484 	telemetry = accel_dev->telemetry;
485 	dev = &GET_DEV(accel_dev);
486 
487 	mutex_lock(&telemetry->wr_lock);
488 
489 	ret = kstrtou32_from_user(userbuf, count, 10, &input);
490 	if (ret)
491 		goto unlock_and_exit;
492 
493 	if (input > tl_data->num_hbuff) {
494 		dev_info(dev, "invalid control input\n");
495 		ret = -EINVAL;
496 		goto unlock_and_exit;
497 	}
498 
499 	/* If input is 0, just stop telemetry. */
500 	if (!input) {
501 		ret = adf_tl_halt(accel_dev);
502 		if (!ret)
503 			ret = count;
504 
505 		goto unlock_and_exit;
506 	}
507 
508 	/* If TL is already enabled, stop it. */
509 	if (atomic_read(&telemetry->state)) {
510 		dev_info(dev, "already enabled, restarting.\n");
511 		ret = adf_tl_halt(accel_dev);
512 		if (ret)
513 			goto unlock_and_exit;
514 	}
515 
516 	ret = adf_tl_run(accel_dev, input);
517 	if (ret)
518 		goto unlock_and_exit;
519 
520 	ret = count;
521 
522 unlock_and_exit:
523 	mutex_unlock(&telemetry->wr_lock);
524 	return ret;
525 }
526 DEFINE_SHOW_STORE_ATTRIBUTE(tl_control);
527 
528 static int adf_tl_dbg_change_rp_index(struct adf_accel_dev *accel_dev,
529 				      unsigned int new_rp_num,
530 				      unsigned int rp_regs_index)
531 {
532 	struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
533 	struct adf_telemetry *telemetry = accel_dev->telemetry;
534 	struct device *dev = &GET_DEV(accel_dev);
535 	unsigned int i;
536 	u8 curr_state;
537 	int ret;
538 
539 	if (new_rp_num >= hw_data->num_rps) {
540 		dev_info(dev, "invalid Ring Pair number selected\n");
541 		return -EINVAL;
542 	}
543 
544 	for (i = 0; i < hw_data->tl_data.max_rp; i++) {
545 		if (telemetry->rp_num_indexes[i] == new_rp_num) {
546 			dev_info(dev, "RP nr: %d is already selected in slot rp_%c_data\n",
547 				 new_rp_num, ADF_TL_DBG_RP_ALPHA_INDEX(i));
548 			return 0;
549 		}
550 	}
551 
552 	dev_dbg(dev, "selecting RP nr %u into slot rp_%c_data\n",
553 		new_rp_num, ADF_TL_DBG_RP_ALPHA_INDEX(rp_regs_index));
554 
555 	curr_state = atomic_read(&telemetry->state);
556 
557 	if (curr_state) {
558 		ret = adf_tl_halt(accel_dev);
559 		if (ret)
560 			return ret;
561 
562 		telemetry->rp_num_indexes[rp_regs_index] = new_rp_num;
563 
564 		ret = adf_tl_run(accel_dev, curr_state);
565 		if (ret)
566 			return ret;
567 	} else {
568 		telemetry->rp_num_indexes[rp_regs_index] = new_rp_num;
569 	}
570 
571 	return 0;
572 }
573 
574 static void tl_print_rp_srv(struct adf_accel_dev *accel_dev, struct seq_file *s,
575 			    u8 rp_idx)
576 {
577 	u32 banks_per_vf = GET_HW_DATA(accel_dev)->num_banks_per_vf;
578 	enum adf_cfg_service_type svc;
579 
580 	seq_printf(s, "%-*s", TL_KEY_MIN_PADDING, RP_SERVICE_TYPE);
581 
582 	svc = GET_SRV_TYPE(accel_dev, rp_idx % banks_per_vf);
583 	switch (svc) {
584 	case COMP:
585 		seq_printf(s, "%*s\n", TL_VALUE_MIN_PADDING, ADF_CFG_DC);
586 		break;
587 	case SYM:
588 		seq_printf(s, "%*s\n", TL_VALUE_MIN_PADDING, ADF_CFG_SYM);
589 		break;
590 	case ASYM:
591 		seq_printf(s, "%*s\n", TL_VALUE_MIN_PADDING, ADF_CFG_ASYM);
592 		break;
593 	case DECOMP:
594 		seq_printf(s, "%*s\n", TL_VALUE_MIN_PADDING, ADF_CFG_DECOMP);
595 		break;
596 	default:
597 		seq_printf(s, "%*s\n", TL_VALUE_MIN_PADDING, TL_RP_SRV_UNKNOWN);
598 		break;
599 	}
600 }
601 
602 static int tl_print_rp_data(struct adf_accel_dev *accel_dev, struct seq_file *s,
603 			    u8 rp_regs_index)
604 {
605 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
606 	struct adf_telemetry *telemetry = accel_dev->telemetry;
607 	const struct adf_tl_dbg_counter *rp_tl_counters;
608 	u8 num_rp_counters = tl_data->num_rp_counters;
609 	size_t rp_regs_sz = tl_data->rp_reg_sz;
610 	struct adf_tl_dbg_counter ctr;
611 	unsigned int i;
612 	u8 rp_idx;
613 	int ret;
614 
615 	if (!atomic_read(&telemetry->state)) {
616 		dev_info(&GET_DEV(accel_dev), "not enabled\n");
617 		return -EPERM;
618 	}
619 
620 	rp_tl_counters = tl_data->rp_counters;
621 	rp_idx = telemetry->rp_num_indexes[rp_regs_index];
622 
623 	if (rp_idx == ADF_TL_RP_REGS_DISABLED) {
624 		dev_info(&GET_DEV(accel_dev), "no RP number selected in rp_%c_data\n",
625 			 ADF_TL_DBG_RP_ALPHA_INDEX(rp_regs_index));
626 		return -EPERM;
627 	}
628 
629 	tl_print_msg_cnt(s, telemetry->msg_cnt);
630 	seq_printf(s, "%-*s", TL_KEY_MIN_PADDING, RP_NUM_INDEX);
631 	seq_printf(s, "%*d\n", TL_VALUE_MIN_PADDING, rp_idx);
632 	tl_print_rp_srv(accel_dev, s, rp_idx);
633 
634 	for (i = 0; i < num_rp_counters; i++) {
635 		ctr = rp_tl_counters[i];
636 		ctr.offset1 += rp_regs_sz * rp_regs_index;
637 		ctr.offset2 += rp_regs_sz * rp_regs_index;
638 		ret = tl_calc_and_print_counter(telemetry, s, &ctr, NULL);
639 		if (ret) {
640 			dev_dbg(&GET_DEV(accel_dev),
641 				"invalid RP counter type\n");
642 			return ret;
643 		}
644 	}
645 
646 	return 0;
647 }
648 
649 static int tl_rp_data_show(struct seq_file *s, void *unused)
650 {
651 	struct adf_accel_dev *accel_dev = s->private;
652 	u8 rp_regs_index;
653 
654 	if (!accel_dev)
655 		return -EINVAL;
656 
657 	rp_regs_index = debugfs_get_aux_num(s->file);
658 
659 	return tl_print_rp_data(accel_dev, s, rp_regs_index);
660 }
661 
662 static ssize_t tl_rp_data_write(struct file *file, const char __user *userbuf,
663 				size_t count, loff_t *ppos)
664 {
665 	struct seq_file *seq_f = file->private_data;
666 	struct adf_accel_dev *accel_dev;
667 	struct adf_telemetry *telemetry;
668 	unsigned int new_rp_num;
669 	u8 rp_regs_index;
670 	int ret;
671 
672 	accel_dev = seq_f->private;
673 	if (!accel_dev)
674 		return -EINVAL;
675 
676 	telemetry = accel_dev->telemetry;
677 
678 	mutex_lock(&telemetry->wr_lock);
679 
680 	rp_regs_index = debugfs_get_aux_num(file);
681 
682 	ret = kstrtou32_from_user(userbuf, count, 10, &new_rp_num);
683 	if (ret)
684 		goto unlock_and_exit;
685 
686 	ret = adf_tl_dbg_change_rp_index(accel_dev, new_rp_num, rp_regs_index);
687 	if (ret)
688 		goto unlock_and_exit;
689 
690 	ret = count;
691 
692 unlock_and_exit:
693 	mutex_unlock(&telemetry->wr_lock);
694 	return ret;
695 }
696 DEFINE_SHOW_STORE_ATTRIBUTE(tl_rp_data);
697 
698 void adf_tl_dbgfs_add(struct adf_accel_dev *accel_dev)
699 {
700 	struct adf_telemetry *telemetry = accel_dev->telemetry;
701 	struct dentry *parent = accel_dev->debugfs_dir;
702 	u8 max_rp = GET_TL_DATA(accel_dev).max_rp;
703 	char name[ADF_TL_RP_REGS_FNAME_SIZE];
704 	struct dentry *dir;
705 	unsigned int i;
706 
707 	if (!telemetry)
708 		return;
709 
710 	dir = debugfs_create_dir("telemetry", parent);
711 	accel_dev->telemetry->dbg_dir = dir;
712 	debugfs_create_file("device_data", 0444, dir, accel_dev, &tl_dev_data_fops);
713 	debugfs_create_file("control", 0644, dir, accel_dev, &tl_control_fops);
714 
715 	for (i = 0; i < max_rp; i++) {
716 		snprintf(name, sizeof(name), ADF_TL_RP_REGS_FNAME,
717 			 ADF_TL_DBG_RP_ALPHA_INDEX(i));
718 		debugfs_create_file_aux_num(name, 0644, dir, accel_dev, i,
719 					    &tl_rp_data_fops);
720 	}
721 }
722 
723 void adf_tl_dbgfs_rm(struct adf_accel_dev *accel_dev)
724 {
725 	struct adf_telemetry *telemetry = accel_dev->telemetry;
726 	struct dentry *dbg_dir;
727 
728 	if (!telemetry)
729 		return;
730 
731 	dbg_dir = telemetry->dbg_dir;
732 
733 	debugfs_remove_recursive(dbg_dir);
734 
735 	if (atomic_read(&telemetry->state))
736 		adf_tl_halt(accel_dev);
737 }
738