Branch data Line data Source code
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 [ # # ]: 0 : return (island_id & 0x3F) == island_id && menum < 12 ?
83 : 0 : (island_id << 4) | (menum + 4) : -1;
84 : : }
85 : :
86 : : static void
87 : 0 : 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 : 0 : sw->type = fw->type;
93 : 0 : sw->name = cache->strtab + rte_le_to_cpu_16(fw->name) % strtab_size;
94 : 0 : sw->addr = ((uint64_t)fw->addr_hi << 32) |
95 : 0 : rte_le_to_cpu_32(fw->addr_lo);
96 : 0 : sw->size = ((uint64_t)fw->size_hi << 32) |
97 : 0 : rte_le_to_cpu_32(fw->size_lo);
98 : :
99 [ # # # ]: 0 : switch (fw->target) {
100 : 0 : case SYM_TGT_LMEM:
101 : 0 : sw->target = NFP_RTSYM_TARGET_LMEM;
102 : 0 : break;
103 : 0 : case SYM_TGT_EMU_CACHE:
104 : 0 : sw->target = NFP_RTSYM_TARGET_EMU_CACHE;
105 : 0 : break;
106 : 0 : default:
107 : 0 : sw->target = fw->target;
108 : 0 : break;
109 : : }
110 : :
111 [ # # ]: 0 : if (fw->menum != 0xff)
112 [ # # ]: 0 : sw->domain = nfp_meid(fw->island, fw->menum);
113 [ # # ]: 0 : else if (fw->island != 0xff)
114 : 0 : sw->domain = fw->island;
115 : : else
116 : 0 : sw->domain = -1;
117 : 0 : }
118 : :
119 : : static struct nfp_rtsym_table *
120 : 0 : 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 [ # # ]: 0 : if (mip == NULL)
137 : : return NULL;
138 : :
139 : 0 : nfp_mip_strtab(mip, &strtab_addr, &strtab_size);
140 : 0 : nfp_mip_symtab(mip, &symtab_addr, &symtab_size);
141 : :
142 [ # # # # : 0 : if (symtab_size == 0 || strtab_size == 0 || symtab_size % sizeof(*rtsymtab) != 0)
# # ]
143 : : return NULL;
144 : :
145 : : /* Align to 64 bits */
146 : 0 : symtab_size = RTE_ALIGN_CEIL(symtab_size, 8);
147 : 0 : strtab_size = RTE_ALIGN_CEIL(strtab_size, 8);
148 : :
149 : 0 : rtsymtab = malloc(symtab_size);
150 [ # # ]: 0 : if (rtsymtab == NULL)
151 : : return NULL;
152 : :
153 : : size = sizeof(*cache);
154 : 0 : size += symtab_size / sizeof(*rtsymtab) * sizeof(struct nfp_rtsym);
155 : 0 : size += strtab_size + 1;
156 : 0 : cache = malloc(size);
157 [ # # ]: 0 : if (cache == NULL)
158 : 0 : goto exit_free_rtsym_raw;
159 : :
160 : 0 : cache->cpp = cpp;
161 : 0 : cache->num = symtab_size / sizeof(*rtsymtab);
162 : 0 : cache->strtab = (void *)&cache->symtab[cache->num];
163 : :
164 : 0 : err = nfp_cpp_read(cpp, dram, symtab_addr, rtsymtab, symtab_size);
165 [ # # ]: 0 : if (err != (int)symtab_size)
166 : 0 : goto exit_free_cache;
167 : :
168 : 0 : err = nfp_cpp_read(cpp, dram, strtab_addr, cache->strtab, strtab_size);
169 [ # # ]: 0 : if (err != (int)strtab_size)
170 : 0 : goto exit_free_cache;
171 : 0 : cache->strtab[strtab_size] = '\0';
172 : :
173 [ # # ]: 0 : for (n = 0; n < cache->num; n++)
174 : 0 : nfp_rtsym_sw_entry_init(cache, strtab_size,
175 : 0 : &cache->symtab[n], &rtsymtab[n]);
176 : :
177 : 0 : free(rtsymtab);
178 : :
179 : 0 : return cache;
180 : :
181 : 0 : exit_free_cache:
182 : 0 : free(cache);
183 : 0 : exit_free_rtsym_raw:
184 : 0 : free(rtsymtab);
185 : 0 : return NULL;
186 : : }
187 : :
188 : : struct nfp_rtsym_table *
189 : 0 : nfp_rtsym_table_read(struct nfp_cpp *cpp)
190 : : {
191 : : struct nfp_mip *mip;
192 : : struct nfp_rtsym_table *rtbl;
193 : :
194 : 0 : mip = nfp_mip_open(cpp);
195 : 0 : rtbl = nfp_rtsym_table_read_real(cpp, mip);
196 : 0 : nfp_mip_close(mip);
197 : :
198 : 0 : 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 : 0 : nfp_rtsym_count(struct nfp_rtsym_table *rtbl)
212 : : {
213 [ # # ]: 0 : if (rtbl == NULL)
214 : : return -EINVAL;
215 : :
216 : 0 : 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 : 0 : nfp_rtsym_get(struct nfp_rtsym_table *rtbl,
232 : : int idx)
233 : : {
234 [ # # ]: 0 : if (rtbl == NULL)
235 : : return NULL;
236 : :
237 [ # # ]: 0 : if (idx >= rtbl->num)
238 : : return NULL;
239 : :
240 : 0 : 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 : 0 : nfp_rtsym_lookup(struct nfp_rtsym_table *rtbl,
256 : : const char *name)
257 : : {
258 : : int n;
259 : :
260 [ # # ]: 0 : if (rtbl == NULL)
261 : : return NULL;
262 : :
263 [ # # ]: 0 : for (n = 0; n < rtbl->num; n++)
264 [ # # ]: 0 : if (strcmp(name, rtbl->symtab[n].name) == 0)
265 : 0 : return &rtbl->symtab[n];
266 : :
267 : : return NULL;
268 : : }
269 : :
270 : : static uint64_t
271 : 0 : nfp_rtsym_size(const struct nfp_rtsym *sym)
272 : : {
273 [ # # # # ]: 0 : switch (sym->type) {
274 : 0 : case NFP_RTSYM_TYPE_NONE:
275 : 0 : PMD_DRV_LOG(ERR, "The type of rtsym '%s' is NONE", sym->name);
276 : 0 : return 0;
277 : 0 : case NFP_RTSYM_TYPE_OBJECT:
278 : : /* FALLTHROUGH */
279 : : case NFP_RTSYM_TYPE_FUNCTION:
280 : 0 : return sym->size;
281 : : case NFP_RTSYM_TYPE_ABS:
282 : : return sizeof(uint64_t);
283 : 0 : default:
284 : 0 : PMD_DRV_LOG(ERR, "Unknown RTSYM type %u", sym->type);
285 : 0 : return 0;
286 : : }
287 : : }
288 : :
289 : : static int
290 : 0 : 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 [ # # ]: 0 : if (sym->type != NFP_RTSYM_TYPE_OBJECT) {
299 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s': direct access to non-object rtsym",
300 : : sym->name);
301 : 0 : return -EINVAL;
302 : : }
303 : :
304 : 0 : *addr = sym->addr + offset;
305 : :
306 [ # # ]: 0 : if (sym->target >= 0) {
307 : 0 : *cpp_id = NFP_CPP_ISLAND_ID(sym->target, action, token, sym->domain);
308 [ # # ]: 0 : } else if (sym->target == NFP_RTSYM_TARGET_EMU_CACHE) {
309 : 0 : int locality_off = nfp_cpp_mu_locality_lsb(cpp);
310 : :
311 : 0 : *addr &= ~(NFP_MU_ADDR_ACCESS_TYPE_MASK << locality_off);
312 : 0 : *addr |= NFP_MU_ADDR_ACCESS_TYPE_DIRECT << locality_off;
313 : :
314 : 0 : *cpp_id = NFP_CPP_ISLAND_ID(NFP_CPP_TARGET_MU, action, token,
315 : : sym->domain);
316 : : } else {
317 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s': unhandled target encoding: %d",
318 : : sym->name, sym->target);
319 : 0 : return -EINVAL;
320 : : }
321 : :
322 : : return 0;
323 : : }
324 : :
325 : : static int
326 : 0 : 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 : 0 : uint64_t sym_size = nfp_rtsym_size(sym);
339 : :
340 [ # # ]: 0 : if (offset >= sym_size) {
341 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' read out of bounds", sym->name);
342 : 0 : return -ENXIO;
343 : : }
344 : :
345 : 0 : if (length > sym_size - offset)
346 : : length = sym_size - offset;
347 : :
348 [ # # ]: 0 : if (sym->type == NFP_RTSYM_TYPE_ABS) {
349 : : union {
350 : : uint64_t value_64;
351 : : uint8_t value_8[8];
352 : : } tmp;
353 : :
354 : 0 : tmp.value_64 = sym->addr;
355 : 0 : memcpy(buf, &tmp.value_8[offset], length);
356 : :
357 : 0 : return length;
358 : : }
359 : :
360 : 0 : err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
361 [ # # ]: 0 : if (err != 0)
362 : : return err;
363 : :
364 : 0 : return nfp_cpp_read(cpp, cpp_id, addr, buf, length);
365 : : }
366 : :
367 : : int
368 : 0 : 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 : 0 : return nfp_rtsym_read_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, buf, len);
375 : : }
376 : :
377 : : static int
378 : 0 : 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 [ # # ]: 0 : if (offset + 4 > nfp_rtsym_size(sym)) {
390 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s': readl out of bounds", sym->name);
391 : 0 : return -ENXIO;
392 : : }
393 : :
394 : 0 : ret = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
395 [ # # ]: 0 : if (ret != 0)
396 : : return ret;
397 : :
398 : 0 : return nfp_cpp_readl(cpp, cpp_id, addr, value);
399 : : }
400 : :
401 : : int
402 : 0 : nfp_rtsym_readl(struct nfp_cpp *cpp,
403 : : const struct nfp_rtsym *sym,
404 : : uint64_t offset,
405 : : uint32_t *value)
406 : : {
407 : 0 : return nfp_rtsym_readl_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value);
408 : : }
409 : :
410 : : static int
411 : 0 : 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 [ # # ]: 0 : if (offset + 8 > nfp_rtsym_size(sym)) {
423 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s': readq out of bounds", sym->name);
424 : 0 : return -ENXIO;
425 : : }
426 : :
427 [ # # ]: 0 : if (sym->type == NFP_RTSYM_TYPE_ABS) {
428 : 0 : *value = sym->addr;
429 : 0 : return 0;
430 : : }
431 : :
432 : 0 : ret = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
433 [ # # ]: 0 : if (ret != 0)
434 : : return ret;
435 : :
436 : 0 : return nfp_cpp_readq(cpp, cpp_id, addr, value);
437 : : }
438 : :
439 : : int
440 : 0 : nfp_rtsym_readq(struct nfp_cpp *cpp,
441 : : const struct nfp_rtsym *sym,
442 : : uint64_t offset,
443 : : uint64_t *value)
444 : : {
445 : 0 : return nfp_rtsym_readq_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value);
446 : : }
447 : :
448 : : static int
449 : 0 : 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 : 0 : uint64_t sym_size = nfp_rtsym_size(sym);
462 : :
463 [ # # ]: 0 : if (offset > sym_size) {
464 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' write out of bounds", sym->name);
465 : 0 : return -ENXIO;
466 : : }
467 : :
468 : 0 : if (length > sym_size - offset)
469 : : length = sym_size - offset;
470 : :
471 : 0 : err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
472 [ # # ]: 0 : if (err != 0)
473 : : return err;
474 : :
475 : 0 : return nfp_cpp_write(cpp, cpp_id, addr, buf, length);
476 : : }
477 : :
478 : : int
479 : 0 : 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 : 0 : return nfp_rtsym_write_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, buf, len);
486 : : }
487 : :
488 : : static int
489 : 0 : 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 [ # # ]: 0 : if (offset + 4 > nfp_rtsym_size(sym)) {
501 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' write out of bounds", sym->name);
502 : 0 : return -ENXIO;
503 : : }
504 : :
505 : 0 : err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
506 [ # # ]: 0 : if (err != 0)
507 : : return err;
508 : :
509 : 0 : return nfp_cpp_writel(cpp, cpp_id, addr, value);
510 : : }
511 : :
512 : : int
513 : 0 : nfp_rtsym_writel(struct nfp_cpp *cpp,
514 : : const struct nfp_rtsym *sym,
515 : : uint64_t offset,
516 : : uint32_t value)
517 : : {
518 : 0 : return nfp_rtsym_writel_real(cpp, sym, NFP_CPP_ACTION_RW, 0, offset, value);
519 : : }
520 : :
521 : : static int
522 : 0 : 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 [ # # ]: 0 : if (offset + 8 > nfp_rtsym_size(sym)) {
534 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' write out of bounds", sym->name);
535 : 0 : return -ENXIO;
536 : : }
537 : :
538 : 0 : err = nfp_rtsym_to_dest(cpp, sym, action, token, offset, &cpp_id, &addr);
539 [ # # ]: 0 : if (err != 0)
540 : : return err;
541 : :
542 : 0 : return nfp_cpp_writeq(cpp, cpp_id, addr, value);
543 : : }
544 : :
545 : : int
546 : 0 : nfp_rtsym_writeq(struct nfp_cpp *cpp,
547 : : const struct nfp_rtsym *sym,
548 : : uint64_t offset,
549 : : uint64_t value)
550 : : {
551 : 0 : 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 : 0 : 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 : 0 : sym = nfp_rtsym_lookup(rtbl, name);
582 [ # # ]: 0 : if (sym == NULL) {
583 : : err = -ENOENT;
584 : 0 : goto exit;
585 : : }
586 : :
587 [ # # # ]: 0 : switch (sym->size) {
588 : 0 : case 4:
589 : 0 : err = nfp_rtsym_readl(rtbl->cpp, sym, 0, &val32);
590 : 0 : val = val32;
591 : 0 : break;
592 : 0 : case 8:
593 : 0 : err = nfp_rtsym_readq(rtbl->cpp, sym, 0, &val);
594 : 0 : break;
595 : 0 : default:
596 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' unsupported size: %#lx",
597 : : name, sym->size);
598 : : err = -EINVAL;
599 : 0 : break;
600 : : }
601 : :
602 : 0 : exit:
603 [ # # ]: 0 : if (error != NULL)
604 : 0 : *error = err;
605 : :
606 [ # # ]: 0 : if (err != 0)
607 : : return ~0ULL;
608 : :
609 : 0 : 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 : 0 : 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 : 0 : sym = nfp_rtsym_lookup(rtbl, name);
639 [ # # ]: 0 : if (sym == NULL)
640 : : return -ENOENT;
641 : :
642 : 0 : sym_size = nfp_rtsym_size(sym);
643 [ # # # ]: 0 : switch (sym_size) {
644 : 0 : case 4:
645 : 0 : err = nfp_rtsym_writel(rtbl->cpp, sym, 0, value);
646 : 0 : break;
647 : 0 : case 8:
648 : 0 : err = nfp_rtsym_writeq(rtbl->cpp, sym, 0, value);
649 : 0 : break;
650 : 0 : default:
651 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s' unsupported size: %#lx",
652 : : name, sym_size);
653 : : err = -EINVAL;
654 : 0 : break;
655 : : }
656 : :
657 : : return err;
658 : : }
659 : :
660 : : uint8_t *
661 : 0 : nfp_rtsym_map(struct nfp_rtsym_table *rtbl,
662 : : const char *name,
663 : : uint32_t min_size,
664 : : struct nfp_cpp_area **area)
665 : : {
666 : : int ret;
667 : : uint8_t *mem;
668 : : uint64_t addr;
669 : : uint32_t cpp_id;
670 : : const struct nfp_rtsym *sym;
671 : :
672 : 0 : sym = nfp_rtsym_lookup(rtbl, name);
673 [ # # ]: 0 : if (sym == NULL) {
674 : 0 : PMD_DRV_LOG(ERR, "Symbol lookup fails for %s", name);
675 : 0 : return NULL;
676 : : }
677 : :
678 : 0 : ret = nfp_rtsym_to_dest(rtbl->cpp, sym, NFP_CPP_ACTION_RW, 0, 0,
679 : : &cpp_id, &addr);
680 [ # # ]: 0 : if (ret != 0) {
681 : 0 : PMD_DRV_LOG(ERR, "rtsym '%s': mapping failed", name);
682 : 0 : return NULL;
683 : : }
684 : :
685 [ # # ]: 0 : if (sym->size < min_size) {
686 : 0 : PMD_DRV_LOG(ERR, "Symbol %s too small (%" PRIu64 " < %u)", name,
687 : : sym->size, min_size);
688 : 0 : return NULL;
689 : : }
690 : :
691 : 0 : mem = nfp_cpp_map_area(rtbl->cpp, cpp_id, addr, sym->size, area);
692 [ # # ]: 0 : if (mem == NULL) {
693 : 0 : PMD_DRV_LOG(ERR, "Failed to map symbol %s", name);
694 : 0 : return NULL;
695 : : }
696 : :
697 : : return mem;
698 : : }
|