xref: /dpdk/drivers/net/nfp/nfpcore/nfp_rtsym.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
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