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