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 : : #include "nfp_cpp.h"
7 : :
8 : : #include <nfp_platform.h>
9 : :
10 : : #include "nfp_logs.h"
11 : : #include "nfp_target.h"
12 : : #include "nfp6000/nfp6000.h"
13 : : #include "nfp6000/nfp_xpb.h"
14 : : #include "nfp6000_pcie.h"
15 : :
16 : : #define NFP_PL_DEVICE_PART_NFP6000 0x6200
17 : : #define NFP_PL_DEVICE_ID 0x00000004
18 : : #define NFP_PL_DEVICE_ID_MASK 0xff
19 : : #define NFP_PL_DEVICE_PART_MASK 0xffff0000
20 : : #define NFP_PL_DEVICE_MODEL_MASK (NFP_PL_DEVICE_PART_MASK | \
21 : : NFP_PL_DEVICE_ID_MASK)
22 : :
23 : : /* NFP CPP handle */
24 : : struct nfp_cpp {
25 : : void *priv; /**< Private data of the low-level implementation */
26 : :
27 : : uint32_t model; /**< Chip model */
28 : : uint16_t interface; /**< Chip interface id */
29 : : uint8_t serial[NFP_SERIAL_LEN]; /**< Chip serial number */
30 : :
31 : : /** Low-level implementation ops */
32 : : const struct nfp_cpp_operations *op;
33 : :
34 : : /*
35 : : * NFP-6xxx originating island IMB CPP Address Translation. CPP Target
36 : : * ID is index into array. Values are obtained at runtime from local
37 : : * island XPB CSRs.
38 : : */
39 : : uint32_t imb_cat_table[16];
40 : :
41 : : /**< MU access type bit offset */
42 : : uint32_t mu_locality_lsb;
43 : :
44 : : bool driver_lock_needed;
45 : : };
46 : :
47 : : /* NFP CPP device area handle */
48 : : struct nfp_cpp_area {
49 : : struct nfp_cpp *cpp;
50 : : char *name;
51 : : uint64_t offset;
52 : : uint32_t size;
53 : : /* Here follows the 'priv' part of nfp_cpp_area. */
54 : : /* Here follows the ASCII name, pointed by @name */
55 : : };
56 : :
57 : : /**
58 : : * Set the private data of the nfp_cpp instance
59 : : *
60 : : * @param cpp
61 : : * NFP CPP operations structure
62 : : *
63 : : * @return
64 : : * Opaque device pointer
65 : : */
66 : : void
67 : 0 : nfp_cpp_priv_set(struct nfp_cpp *cpp,
68 : : void *priv)
69 : : {
70 : 0 : cpp->priv = priv;
71 : 0 : }
72 : :
73 : : /**
74 : : * Return the private data of the nfp_cpp instance
75 : : *
76 : : * @param cpp
77 : : * NFP CPP operations structure
78 : : *
79 : : * @return
80 : : * Opaque device pointer
81 : : */
82 : : void *
83 : 0 : nfp_cpp_priv(struct nfp_cpp *cpp)
84 : : {
85 : 0 : return cpp->priv;
86 : : }
87 : :
88 : : /**
89 : : * Set the model id
90 : : *
91 : : * @param cpp
92 : : * NFP CPP operations structure
93 : : * @param model
94 : : * Model ID
95 : : */
96 : : void
97 : 0 : nfp_cpp_model_set(struct nfp_cpp *cpp,
98 : : uint32_t model)
99 : : {
100 : 0 : cpp->model = model;
101 : 0 : }
102 : :
103 : : /**
104 : : * Retrieve the Model ID of the NFP
105 : : *
106 : : * @param cpp
107 : : * NFP CPP handle
108 : : *
109 : : * @return
110 : : * NFP CPP Model ID
111 : : */
112 : : uint32_t
113 : 0 : nfp_cpp_model(struct nfp_cpp *cpp)
114 : : {
115 : : int err;
116 : : uint32_t model;
117 : :
118 [ # # ]: 0 : if (cpp == NULL)
119 : : return NFP_CPP_MODEL_INVALID;
120 : :
121 : 0 : err = nfp_cpp_model_autodetect(cpp, &model);
122 : :
123 [ # # ]: 0 : if (err < 0)
124 : : return err;
125 : :
126 : 0 : return model;
127 : : }
128 : :
129 : : /**
130 : : * Set the private instance owned data of a nfp_cpp struct
131 : : *
132 : : * @param cpp
133 : : * NFP CPP operations structure
134 : : * @param interface
135 : : * Interface ID
136 : : */
137 : : void
138 : 0 : nfp_cpp_interface_set(struct nfp_cpp *cpp,
139 : : uint32_t interface)
140 : : {
141 : 0 : cpp->interface = interface;
142 : 0 : }
143 : :
144 : : /**
145 : : * Retrieve the Serial ID of the NFP
146 : : *
147 : : * @param cpp
148 : : * NFP CPP handle
149 : : * @param serial
150 : : * Pointer to NFP serial number
151 : : *
152 : : * @return
153 : : * Length of NFP serial number
154 : : */
155 : : uint32_t
156 : 0 : nfp_cpp_serial(struct nfp_cpp *cpp,
157 : : const uint8_t **serial)
158 : : {
159 : 0 : *serial = &cpp->serial[0];
160 : :
161 : 0 : return sizeof(cpp->serial);
162 : : }
163 : :
164 : : /**
165 : : * Set the private instance owned data of a nfp_cpp struct
166 : : *
167 : : * @param cpp
168 : : * NFP CPP operations structure
169 : : * @param serial
170 : : * NFP serial byte array
171 : : * @param serial_len
172 : : * Length of the serial byte array
173 : : */
174 : : void
175 : 0 : nfp_cpp_serial_set(struct nfp_cpp *cpp,
176 : : const uint8_t *serial,
177 : : size_t serial_len)
178 : : {
179 : 0 : memcpy(cpp->serial, serial, serial_len);
180 : 0 : }
181 : :
182 : : /**
183 : : * Retrieve the Interface ID of the NFP
184 : : *
185 : : * @param cpp
186 : : * NFP CPP handle
187 : : *
188 : : * @return
189 : : * NFP CPP Interface ID
190 : : */
191 : : uint16_t
192 : 0 : nfp_cpp_interface(struct nfp_cpp *cpp)
193 : : {
194 [ # # ]: 0 : if (cpp == NULL)
195 : : return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
196 : :
197 : 0 : return cpp->interface;
198 : : }
199 : :
200 : : /**
201 : : * Retrieve the driver need lock flag
202 : : *
203 : : * @param cpp
204 : : * NFP CPP handle
205 : : *
206 : : * @return
207 : : * The driver need lock flag
208 : : */
209 : : bool
210 : 0 : nfp_cpp_driver_need_lock(const struct nfp_cpp *cpp)
211 : : {
212 : 0 : return cpp->driver_lock_needed;
213 : : }
214 : :
215 : : /**
216 : : * Get the privately allocated portion of a NFP CPP area handle
217 : : *
218 : : * @param cpp_area
219 : : * NFP CPP area handle
220 : : *
221 : : * @return
222 : : * Pointer to the private area, or NULL on failure
223 : : */
224 : : void *
225 : 0 : nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
226 : : {
227 : 0 : return &cpp_area[1];
228 : : }
229 : :
230 : : /**
231 : : * Get the NFP CPP handle that is the pci_dev of a NFP CPP area handle
232 : : *
233 : : * @param cpp_area
234 : : * NFP CPP area handle
235 : : *
236 : : * @return
237 : : * NFP CPP handle
238 : : */
239 : : struct nfp_cpp *
240 : 0 : nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
241 : : {
242 : 0 : return cpp_area->cpp;
243 : : }
244 : :
245 : : /**
246 : : * Get the name passed during allocation of the NFP CPP area handle
247 : : *
248 : : * @param cpp_area
249 : : * NFP CPP area handle
250 : : *
251 : : * @return
252 : : * Pointer to the area's name
253 : : */
254 : : const char *
255 : 0 : nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
256 : : {
257 : 0 : return cpp_area->name;
258 : : }
259 : :
260 : : #define NFP_IMB_TGTADDRESSMODECFG_MODE_of(_x) (((_x) >> 13) & 0x7)
261 : : #define NFP_IMB_TGTADDRESSMODECFG_ADDRMODE RTE_BIT32(12)
262 : :
263 : : static int
264 : : nfp_cpp_set_mu_locality_lsb(struct nfp_cpp *cpp)
265 : : {
266 : : int ret;
267 : : int mode;
268 : : int addr40;
269 : : uint32_t imbcppat;
270 : :
271 : 0 : imbcppat = cpp->imb_cat_table[NFP_CPP_TARGET_MU];
272 : 0 : mode = NFP_IMB_TGTADDRESSMODECFG_MODE_of(imbcppat);
273 [ # # ]: 0 : addr40 = imbcppat & NFP_IMB_TGTADDRESSMODECFG_ADDRMODE;
274 : :
275 : : ret = nfp_cppat_mu_locality_lsb(mode, addr40);
276 : : if (ret < 0)
277 : : return ret;
278 : :
279 : 0 : cpp->mu_locality_lsb = ret;
280 : :
281 : : return 0;
282 : : }
283 : :
284 : : uint32_t
285 : 0 : nfp_cpp_mu_locality_lsb(struct nfp_cpp *cpp)
286 : : {
287 : 0 : return cpp->mu_locality_lsb;
288 : : }
289 : :
290 : : /**
291 : : * Allocate and initialize a CPP area structure.
292 : : * The area must later be locked down with an 'acquire' before
293 : : * it can be safely accessed.
294 : : *
295 : : * @param cpp
296 : : * CPP device handle
297 : : * @param dest
298 : : * CPP id
299 : : * @param name
300 : : * Name of region
301 : : * @param address
302 : : * Address of region
303 : : * @param size
304 : : * Size of region
305 : : *
306 : : * @return
307 : : * NFP CPP area handle, or NULL
308 : : *
309 : : * NOTE: @address and @size must be 32-bit aligned values.
310 : : */
311 : : struct nfp_cpp_area *
312 : 0 : nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp,
313 : : uint32_t dest,
314 : : const char *name,
315 : : uint64_t address,
316 : : uint32_t size)
317 : : {
318 : : int err;
319 : : size_t name_len;
320 : : uint32_t target_id;
321 : : uint64_t target_addr;
322 : : struct nfp_cpp_area *area;
323 : :
324 [ # # ]: 0 : if (cpp == NULL)
325 : : return NULL;
326 : :
327 : : /* Remap from cpp_island to cpp_target */
328 : 0 : err = nfp_target_cpp(dest, address, &target_id, &target_addr,
329 : 0 : cpp->imb_cat_table);
330 [ # # ]: 0 : if (err < 0)
331 : : return NULL;
332 : :
333 [ # # ]: 0 : if (name == NULL)
334 : : name = "(reserved)";
335 : :
336 : 0 : name_len = strlen(name) + 1;
337 : 0 : area = calloc(1, sizeof(*area) + cpp->op->area_priv_size + name_len);
338 [ # # ]: 0 : if (area == NULL)
339 : : return NULL;
340 : :
341 : 0 : area->cpp = cpp;
342 : 0 : area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
343 : : memcpy(area->name, name, name_len);
344 : :
345 : 0 : err = cpp->op->area_init(area, target_id, target_addr, size);
346 [ # # ]: 0 : if (err < 0) {
347 : 0 : PMD_DRV_LOG(ERR, "Area init op failed");
348 : 0 : free(area);
349 : 0 : return NULL;
350 : : }
351 : :
352 : 0 : area->offset = target_addr;
353 : 0 : area->size = size;
354 : :
355 : 0 : return area;
356 : : }
357 : :
358 : : /**
359 : : * Allocate and initialize a CPP area structure.
360 : : * The area must later be locked down with an 'acquire' before
361 : : * it can be safely accessed.
362 : : *
363 : : * @param cpp
364 : : * CPP device handle
365 : : * @param dest
366 : : * CPP id
367 : : * @param address
368 : : * Address of region
369 : : * @param size
370 : : * Size of region
371 : : *
372 : : * @return
373 : : * NFP CPP area handle, or NULL
374 : : *
375 : : * NOTE: @address and @size must be 32-bit aligned values.
376 : : */
377 : : struct nfp_cpp_area *
378 : 0 : nfp_cpp_area_alloc(struct nfp_cpp *cpp,
379 : : uint32_t dest,
380 : : uint64_t address,
381 : : size_t size)
382 : : {
383 : 0 : return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
384 : : }
385 : :
386 : : /**
387 : : * Allocate and initialize a CPP area structure, and lock it down so
388 : : * that it can be accessed directly.
389 : : *
390 : : * @param cpp
391 : : * CPP device handle
392 : : * @param destination
393 : : * CPP id
394 : : * @param address
395 : : * Address of region
396 : : * @param size
397 : : * Size of region
398 : : *
399 : : * @return
400 : : * NFP CPP area handle, or NULL
401 : : *
402 : : * NOTE: @address and @size must be 32-bit aligned values.
403 : : *
404 : : * NOTE: The area must also be 'released' when the structure is freed.
405 : : */
406 : : struct nfp_cpp_area *
407 : 0 : nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp,
408 : : uint32_t destination,
409 : : uint64_t address,
410 : : size_t size)
411 : : {
412 : : struct nfp_cpp_area *area;
413 : :
414 : 0 : area = nfp_cpp_area_alloc(cpp, destination, address, size);
415 [ # # ]: 0 : if (area == NULL) {
416 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate CPP area");
417 : 0 : return NULL;
418 : : }
419 : :
420 [ # # ]: 0 : if (nfp_cpp_area_acquire(area) != 0) {
421 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire CPP area");
422 : 0 : nfp_cpp_area_free(area);
423 : 0 : return NULL;
424 : : }
425 : :
426 : : return area;
427 : : }
428 : :
429 : : /**
430 : : * Frees up memory resources held by the CPP area.
431 : : *
432 : : * @param area
433 : : * CPP area handle
434 : : */
435 : : void
436 : 0 : nfp_cpp_area_free(struct nfp_cpp_area *area)
437 : : {
438 [ # # ]: 0 : if (area->cpp->op->area_cleanup != NULL)
439 : 0 : area->cpp->op->area_cleanup(area);
440 : 0 : free(area);
441 : 0 : }
442 : :
443 : : /**
444 : : * Releases CPP area and frees up memory resources held by it.
445 : : *
446 : : * @param area
447 : : * CPP area handle
448 : : */
449 : : void
450 : 0 : nfp_cpp_area_release_free(struct nfp_cpp_area *area)
451 : : {
452 : 0 : nfp_cpp_area_release(area);
453 : 0 : nfp_cpp_area_free(area);
454 : 0 : }
455 : :
456 : : /**
457 : : * Locks down the CPP area for a potential long term activity.
458 : : * Area must always be locked down before being accessed.
459 : : *
460 : : * @param area
461 : : * CPP area handle
462 : : *
463 : : * @return
464 : : * 0 on success, -1 on failure.
465 : : */
466 : : int
467 : 0 : nfp_cpp_area_acquire(struct nfp_cpp_area *area)
468 : : {
469 [ # # ]: 0 : if (area->cpp->op->area_acquire != NULL) {
470 : 0 : int err = area->cpp->op->area_acquire(area);
471 [ # # ]: 0 : if (err < 0) {
472 : 0 : PMD_DRV_LOG(ERR, "Area acquire op failed");
473 : 0 : return -1;
474 : : }
475 : : }
476 : :
477 : : return 0;
478 : : }
479 : :
480 : : /**
481 : : * Releases a previously locked down CPP area.
482 : : *
483 : : * @param area
484 : : * CPP area handle
485 : : */
486 : : void
487 : 0 : nfp_cpp_area_release(struct nfp_cpp_area *area)
488 : : {
489 [ # # ]: 0 : if (area->cpp->op->area_release != NULL)
490 : 0 : area->cpp->op->area_release(area);
491 : 0 : }
492 : :
493 : : /**
494 : : * Returns an iomem pointer for use with readl()/writel() style operations.
495 : : *
496 : : * @param area
497 : : * CPP area handle
498 : : *
499 : : * @return
500 : : * Pointer to the area, or NULL
501 : : *
502 : : * NOTE: Area must have been locked down with an 'acquire'.
503 : : */
504 : : void *
505 : 0 : nfp_cpp_area_iomem(struct nfp_cpp_area *area)
506 : : {
507 : : void *iomem = NULL;
508 : :
509 [ # # ]: 0 : if (area->cpp->op->area_iomem != NULL)
510 : 0 : iomem = area->cpp->op->area_iomem(area);
511 : :
512 : 0 : return iomem;
513 : : }
514 : :
515 : : /**
516 : : * Read data from indicated CPP region.
517 : : *
518 : : * @param area
519 : : * CPP area handle
520 : : * @param offset
521 : : * Offset into CPP area
522 : : * @param address
523 : : * Address to put data into
524 : : * @param length
525 : : * Number of bytes to read
526 : : *
527 : : * @return
528 : : * Length of io, or -ERRNO
529 : : *
530 : : * NOTE: @offset and @length must be 32-bit aligned values.
531 : : * NOTE: Area must have been locked down with an 'acquire'.
532 : : */
533 : : int
534 : 0 : nfp_cpp_area_read(struct nfp_cpp_area *area,
535 : : uint32_t offset,
536 : : void *address,
537 : : size_t length)
538 : : {
539 [ # # ]: 0 : if ((offset + length) > area->size)
540 : : return -EFAULT;
541 : :
542 : 0 : return area->cpp->op->area_read(area, address, offset, length);
543 : : }
544 : :
545 : : /**
546 : : * Write data to indicated CPP region.
547 : : *
548 : : * @param area
549 : : * CPP area handle
550 : : * @param offset
551 : : * Offset into CPP area
552 : : * @param address
553 : : * Address to put data into
554 : : * @param length
555 : : * Number of bytes to read
556 : : *
557 : : * @return
558 : : * Length of io, or -ERRNO
559 : : *
560 : : * NOTE: @offset and @length must be 32-bit aligned values.
561 : : * NOTE: Area must have been locked down with an 'acquire'.
562 : : */
563 : : int
564 : 0 : nfp_cpp_area_write(struct nfp_cpp_area *area,
565 : : uint32_t offset,
566 : : const void *address,
567 : : size_t length)
568 : : {
569 [ # # ]: 0 : if ((offset + length) > area->size)
570 : : return -EFAULT;
571 : :
572 : 0 : return area->cpp->op->area_write(area, address, offset, length);
573 : : }
574 : :
575 : : /*
576 : : * Return the correct CPP address, and fixup xpb_addr as needed,
577 : : * based upon NFP model.
578 : : */
579 : : static uint32_t
580 : 0 : nfp_xpb_to_cpp(struct nfp_cpp *cpp,
581 : : uint32_t *xpb_addr)
582 : : {
583 : : int island;
584 : : uint32_t xpb;
585 : :
586 : : xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
587 : :
588 : : /*
589 : : * Ensure that non-local XPB accesses go out through the
590 : : * global XPBM bus.
591 : : */
592 : 0 : island = (*xpb_addr >> 24) & 0x3f;
593 : :
594 [ # # ]: 0 : if (island == 0)
595 : : return xpb;
596 : :
597 [ # # ]: 0 : if (island != 1) {
598 : 0 : *xpb_addr |= (1 << 30);
599 : 0 : return xpb;
600 : : }
601 : :
602 : : /*
603 : : * Accesses to the ARM Island overlay uses Island 0
604 : : * Global Bit
605 : : */
606 : 0 : *xpb_addr &= ~0x7f000000;
607 [ # # ]: 0 : if (*xpb_addr < 0x60000) {
608 : 0 : *xpb_addr |= (1 << 30);
609 : : } else {
610 : : /* And only non-ARM interfaces use island id = 1 */
611 [ # # ]: 0 : if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
612 : : NFP_CPP_INTERFACE_TYPE_ARM)
613 : 0 : *xpb_addr |= (1 << 24);
614 : : }
615 : :
616 : : return xpb;
617 : : }
618 : :
619 : : /**
620 : : * Read a uint32_t value from an area
621 : : *
622 : : * @param area
623 : : * CPP Area handle
624 : : * @param offset
625 : : * Offset into area
626 : : * @param value
627 : : * Pointer to read buffer
628 : : *
629 : : * @return
630 : : * 0 on success, or -ERRNO
631 : : */
632 : : int
633 : 0 : nfp_cpp_area_readl(struct nfp_cpp_area *area,
634 : : uint32_t offset,
635 : : uint32_t *value)
636 : : {
637 : : int sz;
638 : 0 : uint32_t tmp = 0;
639 : :
640 : 0 : sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
641 [ # # ]: 0 : if (sz != sizeof(tmp))
642 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
643 : :
644 : 0 : *value = rte_le_to_cpu_32(tmp);
645 : :
646 : 0 : return 0;
647 : : }
648 : :
649 : : /**
650 : : * Write a uint32_t vale to an area
651 : : *
652 : : * @param area
653 : : * CPP Area handle
654 : : * @param offset
655 : : * Offset into area
656 : : * @param value
657 : : * Value to write
658 : : *
659 : : * @return
660 : : * 0 on success, or -ERRNO
661 : : */
662 : : int
663 : 0 : nfp_cpp_area_writel(struct nfp_cpp_area *area,
664 : : uint32_t offset,
665 : : uint32_t value)
666 : : {
667 : : int sz;
668 : :
669 : : value = rte_cpu_to_le_32(value);
670 : 0 : sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
671 [ # # ]: 0 : if (sz != sizeof(value))
672 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
673 : :
674 : : return 0;
675 : : }
676 : :
677 : : /**
678 : : * Read a uint64_t value from an area
679 : : *
680 : : * @param area
681 : : * CPP Area handle
682 : : * @param offset
683 : : * Offset into area
684 : : * @param value
685 : : * Pointer to read buffer
686 : : *
687 : : * @return
688 : : * 0 on success, or -ERRNO
689 : : */
690 : : int
691 : 0 : nfp_cpp_area_readq(struct nfp_cpp_area *area,
692 : : uint32_t offset,
693 : : uint64_t *value)
694 : : {
695 : : int sz;
696 : 0 : uint64_t tmp = 0;
697 : :
698 : 0 : sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
699 [ # # ]: 0 : if (sz != sizeof(tmp))
700 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
701 : :
702 : 0 : *value = rte_le_to_cpu_64(tmp);
703 : :
704 : 0 : return 0;
705 : : }
706 : :
707 : : /**
708 : : * Write a uint64_t vale to an area
709 : : *
710 : : * @param area
711 : : * CPP Area handle
712 : : * @param offset
713 : : * Offset into area
714 : : * @param value
715 : : * Value to write
716 : : *
717 : : * @return
718 : : * 0 on success, or -ERRNO
719 : : */
720 : : int
721 : 0 : nfp_cpp_area_writeq(struct nfp_cpp_area *area,
722 : : uint32_t offset,
723 : : uint64_t value)
724 : : {
725 : : int sz;
726 : :
727 : : value = rte_cpu_to_le_64(value);
728 : 0 : sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
729 [ # # ]: 0 : if (sz != sizeof(value))
730 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
731 : :
732 : : return 0;
733 : : }
734 : :
735 : : /**
736 : : * Read a uint32_t value from a CPP location
737 : : *
738 : : * @param cpp
739 : : * CPP device handle
740 : : * @param cpp_id
741 : : * CPP ID for operation
742 : : * @param address
743 : : * Address for operation
744 : : * @param value
745 : : * Pointer to read buffer
746 : : *
747 : : * @return
748 : : * 0 on success, or -ERRNO
749 : : */
750 : : int
751 : 0 : nfp_cpp_readl(struct nfp_cpp *cpp,
752 : : uint32_t cpp_id,
753 : : uint64_t address,
754 : : uint32_t *value)
755 : : {
756 : : int sz;
757 : : uint32_t tmp;
758 : :
759 : 0 : sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
760 [ # # ]: 0 : if (sz != sizeof(tmp))
761 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
762 : :
763 : 0 : *value = rte_le_to_cpu_32(tmp);
764 : :
765 : 0 : return 0;
766 : : }
767 : :
768 : : /**
769 : : * Write a uint32_t value to a CPP location
770 : : *
771 : : * @param cpp
772 : : * CPP device handle
773 : : * @param cpp_id
774 : : * CPP ID for operation
775 : : * @param address
776 : : * Address for operation
777 : : * @param value
778 : : * Value to write
779 : : *
780 : : * @return
781 : : * 0 on success, or -ERRNO
782 : : */
783 : : int
784 : 0 : nfp_cpp_writel(struct nfp_cpp *cpp,
785 : : uint32_t cpp_id,
786 : : uint64_t address,
787 : : uint32_t value)
788 : : {
789 : : int sz;
790 : :
791 : : value = rte_cpu_to_le_32(value);
792 : 0 : sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
793 [ # # ]: 0 : if (sz != sizeof(value))
794 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
795 : :
796 : : return 0;
797 : : }
798 : :
799 : : /**
800 : : * Read a uint64_t value from a CPP location
801 : : *
802 : : * @param cpp
803 : : * CPP device handle
804 : : * @param cpp_id
805 : : * CPP ID for operation
806 : : * @param address
807 : : * Address for operation
808 : : * @param value
809 : : * Pointer to read buffer
810 : : *
811 : : * @return
812 : : * 0 on success, or -ERRNO
813 : : */
814 : : int
815 : 0 : nfp_cpp_readq(struct nfp_cpp *cpp,
816 : : uint32_t cpp_id,
817 : : uint64_t address,
818 : : uint64_t *value)
819 : : {
820 : : int sz;
821 : : uint64_t tmp;
822 : :
823 : 0 : sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
824 : 0 : *value = rte_le_to_cpu_64(tmp);
825 [ # # ]: 0 : if (sz != sizeof(tmp))
826 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
827 : :
828 : : return 0;
829 : : }
830 : :
831 : : /**
832 : : * Write a uint64_t value to a CPP location
833 : : *
834 : : * @param cpp
835 : : * CPP device handle
836 : : * @param cpp_id
837 : : * CPP ID for operation
838 : : * @param address
839 : : * Address for operation
840 : : * @param value
841 : : * Value to write
842 : : *
843 : : * @return
844 : : * 0 on success, or -ERRNO
845 : : */
846 : : int
847 : 0 : nfp_cpp_writeq(struct nfp_cpp *cpp,
848 : : uint32_t cpp_id,
849 : : uint64_t address,
850 : : uint64_t value)
851 : : {
852 : : int sz;
853 : :
854 : : value = rte_cpu_to_le_64(value);
855 : 0 : sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
856 [ # # ]: 0 : if (sz != sizeof(value))
857 [ # # ]: 0 : return sz < 0 ? sz : -EIO;
858 : :
859 : : return 0;
860 : : }
861 : :
862 : : /**
863 : : * Write a uint32_t word to a XPB location
864 : : *
865 : : * @param cpp
866 : : * CPP device handle
867 : : * @param xpb_addr
868 : : * XPB target and address
869 : : * @param value
870 : : * Value to write
871 : : *
872 : : * @return
873 : : * 0 on success, or -ERRNO
874 : : */
875 : : int
876 : 0 : nfp_xpb_writel(struct nfp_cpp *cpp,
877 : : uint32_t xpb_addr,
878 : : uint32_t value)
879 : : {
880 : : uint32_t cpp_dest;
881 : :
882 : 0 : cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
883 : :
884 : 0 : return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
885 : : }
886 : :
887 : : /**
888 : : * Read a uint32_t value from a XPB location
889 : : *
890 : : * @param cpp
891 : : * CPP device handle
892 : : * @param xpb_addr
893 : : * XPB target and address
894 : : * @param value
895 : : * Pointer to read buffer
896 : : *
897 : : * @return
898 : : * 0 on success, or -ERRNO
899 : : */
900 : : int
901 : 0 : nfp_xpb_readl(struct nfp_cpp *cpp,
902 : : uint32_t xpb_addr,
903 : : uint32_t *value)
904 : : {
905 : : uint32_t cpp_dest;
906 : :
907 : 0 : cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
908 : :
909 : 0 : return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
910 : : }
911 : :
912 : : static struct nfp_cpp *
913 : 0 : nfp_cpp_alloc(struct rte_pci_device *pci_dev,
914 : : void *priv,
915 : : bool driver_lock_needed)
916 : : {
917 : : int err;
918 : : size_t target;
919 : : uint32_t xpb_addr;
920 : : struct nfp_cpp *cpp;
921 : : const struct nfp_cpp_operations *ops;
922 : :
923 : 0 : ops = nfp_cpp_transport_operations();
924 [ # # # # ]: 0 : if (ops == NULL || ops->init == NULL)
925 : : return NULL;
926 : :
927 : 0 : cpp = calloc(1, sizeof(*cpp));
928 [ # # ]: 0 : if (cpp == NULL)
929 : : return NULL;
930 : :
931 : 0 : cpp->op = ops;
932 : 0 : cpp->priv = priv;
933 : 0 : cpp->driver_lock_needed = driver_lock_needed;
934 : :
935 : 0 : err = ops->get_interface(pci_dev, &cpp->interface);
936 [ # # ]: 0 : if (err != 0) {
937 : 0 : free(cpp);
938 : 0 : return NULL;
939 : : }
940 : :
941 : 0 : err = ops->get_serial(pci_dev, cpp->serial, NFP_SERIAL_LEN);
942 [ # # ]: 0 : if (err != 0) {
943 : 0 : free(cpp);
944 : 0 : return NULL;
945 : : }
946 : :
947 : : /*
948 : : * NOTE: cpp_lock is NOT locked for op->init,
949 : : * since it may call NFP CPP API operations
950 : : */
951 : 0 : err = cpp->op->init(cpp);
952 [ # # ]: 0 : if (err < 0) {
953 : 0 : PMD_DRV_LOG(ERR, "NFP interface initialization failed");
954 : 0 : free(cpp);
955 : 0 : return NULL;
956 : : }
957 : :
958 : 0 : err = nfp_cpp_model_autodetect(cpp, &cpp->model);
959 [ # # ]: 0 : if (err < 0) {
960 : 0 : PMD_DRV_LOG(ERR, "NFP model detection failed");
961 : 0 : free(cpp);
962 : 0 : return NULL;
963 : : }
964 : :
965 [ # # ]: 0 : for (target = 0; target < RTE_DIM(cpp->imb_cat_table); target++) {
966 : : /* Hardcoded XPB IMB Base, island 0 */
967 : 0 : xpb_addr = 0x000a0000 + (target * 4);
968 : 0 : err = nfp_xpb_readl(cpp, xpb_addr, &cpp->imb_cat_table[target]);
969 [ # # ]: 0 : if (err < 0) {
970 : 0 : PMD_DRV_LOG(ERR, "Can't read CPP mapping from device");
971 : 0 : free(cpp);
972 : 0 : return NULL;
973 : : }
974 : : }
975 : :
976 : : err = nfp_cpp_set_mu_locality_lsb(cpp);
977 : : if (err < 0) {
978 : 0 : PMD_DRV_LOG(ERR, "Can't calculate MU locality bit offset");
979 : 0 : free(cpp);
980 : 0 : return NULL;
981 : : }
982 : :
983 : : return cpp;
984 : : }
985 : :
986 : : /**
987 : : * Free the CPP handle
988 : : *
989 : : * @param cpp
990 : : * CPP handle
991 : : */
992 : : void
993 : 0 : nfp_cpp_free(struct nfp_cpp *cpp)
994 : : {
995 [ # # # # ]: 0 : if (cpp->op != NULL && cpp->op->free != NULL)
996 : 0 : cpp->op->free(cpp);
997 : :
998 : 0 : free(cpp);
999 : 0 : }
1000 : :
1001 : : /**
1002 : : * Create a NFP CPP handle from device
1003 : : *
1004 : : * @param dev
1005 : : * PCI device
1006 : : * @param priv
1007 : : * Private data of low-level implementation
1008 : : * @param driver_lock_needed
1009 : : * Driver lock flag
1010 : : *
1011 : : * @return
1012 : : * NFP CPP handle on success, NULL on failure
1013 : : *
1014 : : * NOTE: On failure, cpp_ops->free will be called!
1015 : : */
1016 : : struct nfp_cpp *
1017 : 0 : nfp_cpp_from_device_name(struct rte_pci_device *dev,
1018 : : void *priv,
1019 : : bool driver_lock_needed)
1020 : : {
1021 : 0 : return nfp_cpp_alloc(dev, priv, driver_lock_needed);
1022 : : }
1023 : :
1024 : : /**
1025 : : * Read from CPP target
1026 : : *
1027 : : * @param cpp
1028 : : * CPP handle
1029 : : * @param destination
1030 : : * CPP id
1031 : : * @param offset
1032 : : * Offset into CPP target
1033 : : * @param address
1034 : : * Buffer for result
1035 : : * @param length
1036 : : * Number of bytes to read
1037 : : *
1038 : : * @return
1039 : : * Length of io, or -ERRNO
1040 : : */
1041 : : int
1042 : 0 : nfp_cpp_read(struct nfp_cpp *cpp,
1043 : : uint32_t destination,
1044 : : uint64_t offset,
1045 : : void *address,
1046 : : size_t length)
1047 : : {
1048 : : int err;
1049 : : struct nfp_cpp_area *area;
1050 : :
1051 : 0 : area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length);
1052 [ # # ]: 0 : if (area == NULL) {
1053 : 0 : PMD_DRV_LOG(ERR, "Area allocation/acquire failed for read");
1054 : 0 : return -EACCES;
1055 : : }
1056 : :
1057 : 0 : err = nfp_cpp_area_read(area, 0, address, length);
1058 : :
1059 : 0 : nfp_cpp_area_release_free(area);
1060 : 0 : return err;
1061 : : }
1062 : :
1063 : : /**
1064 : : * Write to CPP target
1065 : : *
1066 : : * @param cpp
1067 : : * CPP handle
1068 : : * @param destination
1069 : : * CPP id
1070 : : * @param offset
1071 : : * Offset into CPP target
1072 : : * @param address
1073 : : * Buffer to read from
1074 : : * @param length
1075 : : * Number of bytes to write
1076 : : *
1077 : : * @return
1078 : : * Length of io, or -ERRNO
1079 : : */
1080 : : int
1081 : 0 : nfp_cpp_write(struct nfp_cpp *cpp,
1082 : : uint32_t destination,
1083 : : uint64_t offset,
1084 : : const void *address,
1085 : : size_t length)
1086 : : {
1087 : : int err;
1088 : : struct nfp_cpp_area *area;
1089 : :
1090 : 0 : area = nfp_cpp_area_alloc_acquire(cpp, destination, offset, length);
1091 [ # # ]: 0 : if (area == NULL) {
1092 : 0 : PMD_DRV_LOG(ERR, "Area allocation/acquire failed for write");
1093 : 0 : return -EACCES;
1094 : : }
1095 : :
1096 : 0 : err = nfp_cpp_area_write(area, 0, address, length);
1097 : :
1098 : 0 : nfp_cpp_area_release_free(area);
1099 : 0 : return err;
1100 : : }
1101 : :
1102 : : /*
1103 : : * NOTE: This code should not use nfp_xpb_* functions,
1104 : : * as those are model-specific
1105 : : */
1106 : : uint32_t
1107 : 0 : nfp_cpp_model_autodetect(struct nfp_cpp *cpp,
1108 : : uint32_t *model)
1109 : : {
1110 : : int err;
1111 : : uint32_t reg;
1112 : :
1113 : 0 : err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
1114 : : ®);
1115 [ # # ]: 0 : if (err < 0)
1116 : 0 : return err;
1117 : :
1118 : 0 : *model = reg & NFP_PL_DEVICE_MODEL_MASK;
1119 : : /* Disambiguate the NFP4000/NFP5000/NFP6000 chips */
1120 [ # # ]: 0 : if (FIELD_GET(NFP_PL_DEVICE_PART_MASK, reg) ==
1121 : : NFP_PL_DEVICE_PART_NFP6000) {
1122 [ # # ]: 0 : if ((*model & NFP_PL_DEVICE_ID_MASK) != 0)
1123 : 0 : *model -= 0x10;
1124 : : }
1125 : :
1126 : : return 0;
1127 : : }
1128 : :
1129 : : /**
1130 : : * Map an area of IOMEM access.
1131 : : * To undo the effect of this function call @nfp_cpp_area_release_free(*area).
1132 : : *
1133 : : * @param cpp
1134 : : * NFP CPP handler
1135 : : * @param cpp_id
1136 : : * CPP id
1137 : : * @param addr
1138 : : * CPP address
1139 : : * @param size
1140 : : * Size of the area
1141 : : * @param area
1142 : : * Area handle (output)
1143 : : *
1144 : : * @return
1145 : : * Pointer to memory mapped area or NULL
1146 : : */
1147 : : uint8_t *
1148 : 0 : nfp_cpp_map_area(struct nfp_cpp *cpp,
1149 : : uint32_t cpp_id,
1150 : : uint64_t addr,
1151 : : uint32_t size,
1152 : : struct nfp_cpp_area **area)
1153 : : {
1154 : : uint8_t *res;
1155 : :
1156 : 0 : *area = nfp_cpp_area_alloc_acquire(cpp, cpp_id, addr, size);
1157 [ # # ]: 0 : if (*area == NULL) {
1158 : 0 : PMD_DRV_LOG(ERR, "Area allocation/acquire failed for map");
1159 : 0 : goto err_eio;
1160 : : }
1161 : :
1162 : 0 : res = nfp_cpp_area_iomem(*area);
1163 [ # # ]: 0 : if (res == NULL)
1164 : 0 : goto err_release_free;
1165 : :
1166 : : return res;
1167 : :
1168 : : err_release_free:
1169 : 0 : nfp_cpp_area_release_free(*area);
1170 : : err_eio:
1171 : : return NULL;
1172 : : }
|