1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018 Netronome Systems, Inc. 3 * All rights reserved. 4 */ 5 6 /* 7 * nfp_rtsym.c 8 * Interface for accessing run-time symbol table 9 */ 10 11 #include "nfp_rtsym.h" 12 13 #include <rte_byteorder.h> 14 15 #include "nfp_logs.h" 16 #include "nfp_mip.h" 17 #include "nfp_target.h" 18 #include "nfp6000/nfp6000.h" 19 20 enum nfp_rtsym_type { 21 NFP_RTSYM_TYPE_NONE, 22 NFP_RTSYM_TYPE_OBJECT, 23 NFP_RTSYM_TYPE_FUNCTION, 24 NFP_RTSYM_TYPE_ABS, 25 }; 26 27 #define NFP_RTSYM_TARGET_NONE 0 28 #define NFP_RTSYM_TARGET_LMEM -1 29 #define NFP_RTSYM_TARGET_EMU_CACHE -7 30 31 /* These need to match the linker */ 32 #define SYM_TGT_LMEM 0 33 #define SYM_TGT_EMU_CACHE 0x17 34 35 struct nfp_rtsym_entry { 36 uint8_t type; 37 uint8_t target; 38 uint8_t island; 39 uint8_t addr_hi; 40 uint32_t addr_lo; 41 uint16_t name; 42 uint8_t menum; 43 uint8_t size_hi; 44 uint32_t size_lo; 45 }; 46 47 /* 48 * Structure describing a run-time NFP symbol. 49 * 50 * The memory target of the symbol is generally the CPP target number and can be 51 * used directly by the nfp_cpp API calls. However, in some cases (i.e., for 52 * local memory or control store) the target is encoded using a negative number. 53 * 54 * When the target type can not be used to fully describe the location of a 55 * symbol the domain field is used to further specify the location (i.e., the 56 * specific ME or island number). 57 * 58 * For ME target resources, 'domain' is an MEID. 59 * For Island target resources, 'domain' is an island ID, with the one exception 60 * of "sram" symbols for backward compatibility, which are viewed as global. 61 */ 62 struct nfp_rtsym { 63 const char *name; /**< Symbol name */ 64 uint64_t addr; /**< Address in the domain/target's address space */ 65 uint64_t size; /**< Size (in bytes) of the symbol */ 66 enum nfp_rtsym_type type; /**< NFP_RTSYM_TYPE_* of the symbol */ 67 int target; /**< CPP target identifier, or NFP_RTSYM_TARGET_* */ 68 int domain; /**< CPP target domain */ 69 }; 70 71 struct nfp_rtsym_table { 72 struct nfp_cpp *cpp; 73 int num; 74 char *strtab; 75 struct nfp_rtsym symtab[]; 76 }; 77 78 static int 79 nfp_meid(uint8_t island_id, 80 uint8_t menum) 81 { 82 return (island_id & 0x3F) == island_id && menum < 12 ? 83 (island_id << 4) | (menum + 4) : -1; 84 } 85 86 static void 87 nfp_rtsym_sw_entry_init(struct nfp_rtsym_table *cache, 88 uint32_t strtab_size, 89 struct nfp_rtsym *sw, 90 struct nfp_rtsym_entry *fw) 91 { 92 sw->type = fw->type; 93 sw->name = cache->strtab + rte_le_to_cpu_16(fw->name) % strtab_size; 94 sw->addr = ((uint64_t)fw->addr_hi << 32) | 95 rte_le_to_cpu_32(fw->addr_lo); 96 sw->size = ((uint64_t)fw->size_hi << 32) | 97 rte_le_to_cpu_32(fw->size_lo); 98 99 switch (fw->target) { 100 case SYM_TGT_LMEM: 101 sw->target = NFP_RTSYM_TARGET_LMEM; 102 break; 103 case SYM_TGT_EMU_CACHE: 104 sw->target = NFP_RTSYM_TARGET_EMU_CACHE; 105 break; 106 default: 107 sw->target = fw->target; 108 break; 109 } 110 111 if (fw->menum != 0xff) 112 sw->domain = nfp_meid(fw->island, fw->menum); 113 else if (fw->island != 0xff) 114 sw->domain = fw->island; 115 else 116 sw->domain = -1; 117 } 118 119 static struct nfp_rtsym_table * 120 nfp_rtsym_table_read_real(struct nfp_cpp *cpp, 121 const struct nfp_mip *mip) 122 { 123 int n; 124 int err; 125 uint32_t size; 126 uint32_t strtab_addr; 127 uint32_t symtab_addr; 128 uint32_t strtab_size; 129 uint32_t symtab_size; 130 struct nfp_rtsym_table *cache; 131 struct nfp_rtsym_entry *rtsymtab; 132 const uint32_t dram = 133 NFP_CPP_ID(NFP_CPP_TARGET_MU, NFP_CPP_ACTION_RW, 0) | 134 NFP_ISL_EMEM0; 135 136 if (mip == NULL) 137 return NULL; 138 139 nfp_mip_strtab(mip, &strtab_addr, &strtab_size); 140 nfp_mip_symtab(mip, &symtab_addr, &symtab_size); 141 142 if (symtab_size == 0 || strtab_size == 0 || symtab_size % sizeof(*rtsymtab) != 0) 143 return NULL; 144 145 /* Align to 64 bits */ 146 symtab_size = RTE_ALIGN_CEIL(symtab_size, 8); 147 strtab_size = RTE_ALIGN_CEIL(strtab_size, 8); 148 149 rtsymtab = malloc(symtab_size); 150 if (rtsymtab == NULL) 151 return NULL; 152 153 size = sizeof(*cache); 154 size += symtab_size / sizeof(*rtsymtab) * sizeof(struct nfp_rtsym); 155 size += strtab_size + 1; 156 cache = malloc(size); 157 if (cache == NULL) 158 goto exit_free_rtsym_raw; 159 160 cache->cpp = cpp; 161 cache->num = symtab_size / sizeof(*rtsymtab); 162 cache->strtab = (void *)&cache->symtab[cache->num]; 163 164 err = nfp_cpp_read(cpp, dram, symtab_addr, rtsymtab, symtab_size); 165 if (err != (int)symtab_size) 166 goto exit_free_cache; 167 168 err = nfp_cpp_read(cpp, dram, strtab_addr, cache->strtab, strtab_size); 169 if (err != (int)strtab_size) 170 goto exit_free_cache; 171 cache->strtab[strtab_size] = '\0'; 172 173 for (n = 0; n < cache->num; n++) 174 nfp_rtsym_sw_entry_init(cache, strtab_size, 175 &cache->symtab[n], &rtsymtab[n]); 176 177 free(rtsymtab); 178 179 return cache; 180 181 exit_free_cache: 182 free(cache); 183 exit_free_rtsym_raw: 184 free(rtsymtab); 185 return NULL; 186 } 187 188 struct nfp_rtsym_table * 189 nfp_rtsym_table_read(struct nfp_cpp *cpp) 190 { 191 struct nfp_mip *mip; 192 struct nfp_rtsym_table *rtbl; 193 194 mip = nfp_mip_open(cpp); 195 rtbl = nfp_rtsym_table_read_real(cpp, mip); 196 nfp_mip_close(mip); 197 198 return rtbl; 199 } 200 201 /** 202 * Get the number of RTSYM descriptors 203 * 204 * @param rtbl 205 * NFP RTSYM table 206 * 207 * @return 208 * Number of RTSYM descriptors 209 */ 210 int 211 nfp_rtsym_count(struct nfp_rtsym_table *rtbl) 212 { 213 if (rtbl == NULL) 214 return -EINVAL; 215 216 return rtbl->num; 217 } 218 219 /** 220 * Get the Nth RTSYM descriptor 221 * 222 * @param rtbl 223 * NFP RTSYM table 224 * @param idx 225 * Index (0-based) of the RTSYM descriptor 226 * 227 * @return 228 * Const pointer to a struct nfp_rtsym descriptor, or NULL 229 */ 230 const struct nfp_rtsym * 231 nfp_rtsym_get(struct nfp_rtsym_table *rtbl, 232 int idx) 233 { 234 if (rtbl == NULL) 235 return NULL; 236 237 if (idx >= rtbl->num) 238 return NULL; 239 240 return &rtbl->symtab[idx]; 241 } 242 243 /** 244 * Return the RTSYM descriptor for a symbol name 245 * 246 * @param rtbl 247 * NFP RTSYM table 248 * @param name 249 * Symbol name 250 * 251 * @return 252 * Const pointer to a struct nfp_rtsym descriptor, or NULL 253 */ 254 const struct nfp_rtsym * 255 nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl, 256 const char *name) 257 { 258 int n; 259 260 if (rtbl == NULL) 261 return NULL; 262 263 for (n = 0; n < rtbl->num; n++) 264 if (strcmp(name, rtbl->symtab[n].name) == 0) 265 return &rtbl->symtab[n]; 266 267 return NULL; 268 } 269 270 static uint64_t 271 nfp_rtsym_size(const struct nfp_rtsym *sym) 272 { 273 switch (sym->type) { 274 case NFP_RTSYM_TYPE_NONE: 275 PMD_DRV_LOG(ERR, "The type of rtsym '%s' is NONE.", sym->name); 276 return 0; 277 case NFP_RTSYM_TYPE_OBJECT: 278 /* FALLTHROUGH */ 279 case NFP_RTSYM_TYPE_FUNCTION: 280 return sym->size; 281 case NFP_RTSYM_TYPE_ABS: 282 return sizeof(uint64_t); 283 default: 284 PMD_DRV_LOG(ERR, "Unknown RTSYM type %u.", sym->type); 285 return 0; 286 } 287 } 288 289 static int 290 nfp_rtsym_to_dest(struct nfp_cpp *cpp, 291 const struct nfp_rtsym *sym, 292 uint8_t action, 293 uint8_t token, 294 uint64_t offset, 295 uint32_t *cpp_id, 296 uint64_t *addr) 297 { 298 if (sym->type != NFP_RTSYM_TYPE_OBJECT) { 299 PMD_DRV_LOG(ERR, "RTSYM '%s': direct access to non-object rtsym.", 300 sym->name); 301 return -EINVAL; 302 } 303 304 *addr = sym->addr + offset; 305 306 if (sym->target >= 0) { 307 *cpp_id = NFP_CPP_ISLAND_ID(sym->target, action, token, sym->domain); 308 } else if (sym->target == NFP_RTSYM_TARGET_EMU_CACHE) { 309 int locality_off = nfp_cpp_mu_locality_lsb(cpp); 310 311 *addr &= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK << locality_off); 312 *addr |= NFP_MU_ADDR_ACCESS_TYPE_DIRECT << locality_off; 313 314 *cpp_id = NFP_CPP_ISLAND_ID(NFP_CPP_TARGET_MU, action, token, 315 sym->domain); 316 } else { 317 PMD_DRV_LOG(ERR, "RTSYM '%s': unhandled target encoding: %d.", 318 sym->name, sym->target); 319 return -EINVAL; 320 } 321 322 return 0; 323 } 324 325 static int 326 nfp_rtsym_read_real(struct nfp_cpp *cpp, 327 const struct nfp_rtsym *sym, 328 uint8_t action, 329 uint8_t token, 330 uint64_t offset, 331 void *buf, 332 size_t len) 333 { 334 int err; 335 uint64_t addr; 336 uint32_t cpp_id; 337 size_t length = len; 338 uint64_t sym_size = nfp_rtsym_size(sym); 339 340 if (offset >= sym_size) { 341 PMD_DRV_LOG(ERR, "RTSYM '%s' read out of bounds.", sym->name); 342 return -ENXIO; 343 } 344 345 if (length > sym_size - offset) 346 length = sym_size - offset; 347 348 if (sym->type == NFP_RTSYM_TYPE_ABS) { 349 union { 350 uint64_t value_64; 351 uint8_t value_8[8]; 352 } tmp; 353 354 tmp.value_64 = sym->addr; 355 memcpy(buf, &tmp.value_8[offset], length); 356 357 return length; 358 } 359 360 err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 361 if (err != 0) 362 return err; 363 364 return nfp_cpp_read(cpp, cpp_id, addr, buf, length); 365 } 366 367 int 368 nfp_rtsym_read(struct nfp_cpp *cpp, 369 const struct nfp_rtsym *sym, 370 uint64_t offset, 371 void *buf, 372 size_t len) 373 { 374 return nfp_rtsym_read_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, buf, len); 375 } 376 377 static int 378 nfp_rtsym_readl_real(struct nfp_cpp *cpp, 379 const struct nfp_rtsym *sym, 380 uint8_t action, 381 uint8_t token, 382 uint64_t offset, 383 uint32_t *value) 384 { 385 int ret; 386 uint64_t addr; 387 uint32_t cpp_id; 388 389 if (offset + 4 > nfp_rtsym_size(sym)) { 390 PMD_DRV_LOG(ERR, "RTSYM '%s': readl out of bounds.", sym->name); 391 return -ENXIO; 392 } 393 394 ret = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 395 if (ret != 0) 396 return ret; 397 398 return nfp_cpp_readl(cpp, cpp_id, addr, value); 399 } 400 401 int 402 nfp_rtsym_readl(struct nfp_cpp *cpp, 403 const struct nfp_rtsym *sym, 404 uint64_t offset, 405 uint32_t *value) 406 { 407 return nfp_rtsym_readl_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value); 408 } 409 410 static int 411 nfp_rtsym_readq_real(struct nfp_cpp *cpp, 412 const struct nfp_rtsym *sym, 413 uint8_t action, 414 uint8_t token, 415 uint64_t offset, 416 uint64_t *value) 417 { 418 int ret; 419 uint64_t addr; 420 uint32_t cpp_id; 421 422 if (offset + 8 > nfp_rtsym_size(sym)) { 423 PMD_DRV_LOG(ERR, "RTSYM '%s': readq out of bounds.", sym->name); 424 return -ENXIO; 425 } 426 427 if (sym->type == NFP_RTSYM_TYPE_ABS) { 428 *value = sym->addr; 429 return 0; 430 } 431 432 ret = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 433 if (ret != 0) 434 return ret; 435 436 return nfp_cpp_readq(cpp, cpp_id, addr, value); 437 } 438 439 int 440 nfp_rtsym_readq(struct nfp_cpp *cpp, 441 const struct nfp_rtsym *sym, 442 uint64_t offset, 443 uint64_t *value) 444 { 445 return nfp_rtsym_readq_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value); 446 } 447 448 static int 449 nfp_rtsym_write_real(struct nfp_cpp *cpp, 450 const struct nfp_rtsym *sym, 451 uint8_t action, 452 uint8_t token, 453 uint64_t offset, 454 void *buf, 455 size_t len) 456 { 457 int err; 458 uint64_t addr; 459 uint32_t cpp_id; 460 size_t length = len; 461 uint64_t sym_size = nfp_rtsym_size(sym); 462 463 if (offset > sym_size) { 464 PMD_DRV_LOG(ERR, "RTSYM '%s' write out of bounds.", sym->name); 465 return -ENXIO; 466 } 467 468 if (length > sym_size - offset) 469 length = sym_size - offset; 470 471 err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 472 if (err != 0) 473 return err; 474 475 return nfp_cpp_write(cpp, cpp_id, addr, buf, length); 476 } 477 478 int 479 nfp_rtsym_write(struct nfp_cpp *cpp, 480 const struct nfp_rtsym *sym, 481 uint64_t offset, 482 void *buf, 483 size_t len) 484 { 485 return nfp_rtsym_write_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, buf, len); 486 } 487 488 static int 489 nfp_rtsym_writel_real(struct nfp_cpp *cpp, 490 const struct nfp_rtsym *sym, 491 uint8_t action, 492 uint8_t token, 493 uint64_t offset, 494 uint32_t value) 495 { 496 int err; 497 uint64_t addr; 498 uint32_t cpp_id; 499 500 if (offset + 4 > nfp_rtsym_size(sym)) { 501 PMD_DRV_LOG(ERR, "RTSYM '%s' write out of bounds.", sym->name); 502 return -ENXIO; 503 } 504 505 err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 506 if (err != 0) 507 return err; 508 509 return nfp_cpp_writel(cpp, cpp_id, addr, value); 510 } 511 512 int 513 nfp_rtsym_writel(struct nfp_cpp *cpp, 514 const struct nfp_rtsym *sym, 515 uint64_t offset, 516 uint32_t value) 517 { 518 return nfp_rtsym_writel_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value); 519 } 520 521 static int 522 nfp_rtsym_writeq_real(struct nfp_cpp *cpp, 523 const struct nfp_rtsym *sym, 524 uint8_t action, 525 uint8_t token, 526 uint64_t offset, 527 uint64_t value) 528 { 529 int err; 530 uint64_t addr; 531 uint32_t cpp_id; 532 533 if (offset + 8 > nfp_rtsym_size(sym)) { 534 PMD_DRV_LOG(ERR, "RTSYM '%s' write out of bounds.", sym->name); 535 return -ENXIO; 536 } 537 538 err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr); 539 if (err != 0) 540 return err; 541 542 return nfp_cpp_writeq(cpp, cpp_id, addr, value); 543 } 544 545 int 546 nfp_rtsym_writeq(struct nfp_cpp *cpp, 547 const struct nfp_rtsym *sym, 548 uint64_t offset, 549 uint64_t value) 550 { 551 return nfp_rtsym_writeq_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value); 552 } 553 554 /** 555 * Read a simple unsigned scalar value from symbol 556 * 557 * Lookup a symbol, map, read it and return it's value. Value of the symbol 558 * will be interpreted as a simple little-endian unsigned value. Symbol can 559 * be 4 or 8 bytes in size. 560 * 561 * @param rtbl 562 * NFP RTSYM table 563 * @param name 564 * Symbol name 565 * @param error 566 * Pointer to error code (optional) 567 * 568 * @return 569 * Value read, on error sets the error and returns ~0ULL. 570 */ 571 uint64_t 572 nfp_rtsym_read_le(struct nfp_rtsym_table *rtbl, 573 const char *name, 574 int *error) 575 { 576 int err; 577 uint64_t val; 578 uint32_t val32; 579 const struct nfp_rtsym *sym; 580 581 sym = nfp_rtsym_lookup(rtbl, name); 582 if (sym == NULL) { 583 err = -ENOENT; 584 goto exit; 585 } 586 587 switch (sym->size) { 588 case 4: 589 err = nfp_rtsym_readl(rtbl->cpp, sym, 0, &val32); 590 val = val32; 591 break; 592 case 8: 593 err = nfp_rtsym_readq(rtbl->cpp, sym, 0, &val); 594 break; 595 default: 596 PMD_DRV_LOG(ERR, "RTSYM '%s' unsupported size: %#lx.", 597 name, sym->size); 598 err = -EINVAL; 599 break; 600 } 601 602 exit: 603 if (error != NULL) 604 *error = err; 605 606 if (err != 0) 607 return ~0ULL; 608 609 return val; 610 } 611 612 /** 613 * Write an unsigned scalar value to a symbol 614 * 615 * Lookup a symbol and write a value to it. Symbol can be 4 or 8 bytes in size. 616 * If 4 bytes then the lower 32-bits of 'value' are used. Value will be 617 * written as simple little-endian unsigned value. 618 * 619 * @param rtbl 620 * NFP RTSYM table 621 * @param name 622 * Symbol name 623 * @param value 624 * Value to write 625 * 626 * @return 627 * 0 on success or error code. 628 */ 629 int 630 nfp_rtsym_write_le(struct nfp_rtsym_table *rtbl, 631 const char *name, 632 uint64_t value) 633 { 634 int err; 635 uint64_t sym_size; 636 const struct nfp_rtsym *sym; 637 638 sym = nfp_rtsym_lookup(rtbl, name); 639 if (sym == NULL) 640 return -ENOENT; 641 642 sym_size = nfp_rtsym_size(sym); 643 switch (sym_size) { 644 case 4: 645 err = nfp_rtsym_writel(rtbl->cpp, sym, 0, value); 646 break; 647 case 8: 648 err = nfp_rtsym_writeq(rtbl->cpp, sym, 0, value); 649 break; 650 default: 651 PMD_DRV_LOG(ERR, "RTSYM '%s' unsupported size: %#lx.", 652 name, sym_size); 653 err = -EINVAL; 654 break; 655 } 656 657 return err; 658 } 659 660 uint8_t * 661 nfp_rtsym_map_offset(struct nfp_rtsym_table *rtbl, 662 const char *name, 663 uint32_t offset, 664 uint32_t min_size, 665 struct nfp_cpp_area **area) 666 { 667 int ret; 668 uint8_t *mem; 669 uint64_t addr; 670 uint32_t cpp_id; 671 const struct nfp_rtsym *sym; 672 673 sym = nfp_rtsym_lookup(rtbl, name); 674 if (sym == NULL) { 675 PMD_DRV_LOG(ERR, "Symbol lookup fails for %s.", name); 676 return NULL; 677 } 678 679 ret = nfp_rtsym_to_dest(rtbl->cpp, sym, NFP_CPP_ACTION_RW, 0, 0, 680 &cpp_id, &addr); 681 if (ret != 0) { 682 PMD_DRV_LOG(ERR, "RTSYM '%s': mapping failed.", name); 683 return NULL; 684 } 685 686 if (sym->size < min_size) { 687 PMD_DRV_LOG(ERR, "Symbol %s too small (%" PRIu64 " < %u).", name, 688 sym->size, min_size); 689 return NULL; 690 } 691 692 mem = nfp_cpp_map_area(rtbl->cpp, cpp_id, addr + offset, sym->size, area); 693 if (mem == NULL) { 694 PMD_DRV_LOG(ERR, "Failed to map symbol %s.", name); 695 return NULL; 696 } 697 698 return mem; 699 } 700 701 uint8_t * 702 nfp_rtsym_map(struct nfp_rtsym_table *rtbl, 703 const char *name, 704 uint32_t min_size, 705 struct nfp_cpp_area **area) 706 { 707 return nfp_rtsym_map_offset(rtbl, name, 0, min_size, area); 708 } 709 710 /** 711 * Pop a simple unsigned scalar value from ring 712 * 713 * Lookup the symbol table for ring base and address, then pop value base on 714 * the ring with cpp read and write operation. 715 * 716 * @param rtbl 717 * NFP run-time symbol table 718 * @param aux_name 719 * The auxiliary rtsym table name which can ensure ring base and address 720 * @param name 721 * The rtsym table name which can handle the ring 722 * @param value 723 * Pop this value from ring 724 * 725 * @return 726 * 0 on success, negative errno otherwise. 727 */ 728 int 729 nfp_rtsym_readl_indirect(struct nfp_rtsym_table *rtbl, 730 const char *aux_name, 731 const char *name, 732 uint32_t *value) 733 { 734 int ret; 735 uint32_t cpp_id; 736 const struct nfp_rtsym *sym; 737 const struct nfp_rtsym *aux_sym; 738 739 if (value == NULL) 740 return -EINVAL; 741 742 aux_sym = nfp_rtsym_lookup(rtbl, aux_name); 743 if (aux_sym == NULL) { 744 PMD_DRV_LOG(ERR, "Failed to find symbol %s.", aux_name); 745 return -ENOENT; 746 } 747 748 sym = nfp_rtsym_lookup(rtbl, name); 749 if (sym == NULL) { 750 PMD_DRV_LOG(ERR, "Failed to find symbol %s.", name); 751 return -ENOENT; 752 } 753 754 /* Ring Pop */ 755 cpp_id = NFP_CPP_ISLAND_ID(aux_sym->target, 22, 0, aux_sym->domain); 756 ret = nfp_cpp_readl(rtbl->cpp, cpp_id, sym->addr, value); 757 if (ret != 0) 758 return -EIO; 759 760 return 0; 761 } 762 763 /** 764 * Push a simple unsigned scalar value to ring 765 * 766 * Lookup the symbol table for ring base and address, then Push value base on 767 * the ring with cpp read and write operation. 768 * 769 * @param rtbl 770 * NFP run-time symbol table 771 * @param aux_name 772 * The auxiliary rtsym table name which can ensure ring base and address 773 * @param name 774 * The rtsym table name which can handle the ring 775 * @param value 776 * Push this value to ring 777 * 778 * @return 779 * 0 on success, negative errno otherwise. 780 */ 781 int 782 nfp_rtsym_writel_indirect(struct nfp_rtsym_table *rtbl, 783 const char *aux_name, 784 const char *name, 785 uint32_t value) 786 { 787 int ret; 788 uint32_t cpp_id; 789 const struct nfp_rtsym *sym; 790 const struct nfp_rtsym *aux_sym; 791 792 aux_sym = nfp_rtsym_lookup(rtbl, aux_name); 793 if (aux_sym == NULL) { 794 PMD_DRV_LOG(ERR, "Failed to find symbol %s.", aux_name); 795 return -ENOENT; 796 } 797 798 sym = nfp_rtsym_lookup(rtbl, name); 799 if (sym == NULL) { 800 PMD_DRV_LOG(ERR, "Failed to find symbol %s.", name); 801 return -ENOENT; 802 } 803 804 /* Ring Put */ 805 cpp_id = NFP_CPP_ISLAND_ID(aux_sym->target, 20, 0, aux_sym->domain); 806 ret = nfp_cpp_writel(rtbl->cpp, cpp_id, sym->addr, value); 807 if (ret != 0) 808 return -EIO; 809 810 return 0; 811 } 812