1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
3 * All rights reserved.
4 */
5
6 #include <assert.h>
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 #include <sys/types.h>
13
14 #include <rte_byteorder.h>
15 #include <ethdev_pci.h>
16
17 #include "nfp_cpp.h"
18 #include "nfp_target.h"
19 #include "nfp6000/nfp6000.h"
20 #include "nfp6000/nfp_xpb.h"
21 #include "nfp_nffw.h"
22
23 #define NFP_PL_DEVICE_ID 0x00000004
24 #define NFP_PL_DEVICE_ID_MASK 0xff
25 #define NFP_PL_DEVICE_PART_MASK 0xffff0000
26 #define NFP_PL_DEVICE_MODEL_MASK (NFP_PL_DEVICE_PART_MASK | \
27 NFP_PL_DEVICE_ID_MASK)
28
29 void
nfp_cpp_priv_set(struct nfp_cpp * cpp,void * priv)30 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
31 {
32 cpp->priv = priv;
33 }
34
35 void *
nfp_cpp_priv(struct nfp_cpp * cpp)36 nfp_cpp_priv(struct nfp_cpp *cpp)
37 {
38 return cpp->priv;
39 }
40
41 void
nfp_cpp_model_set(struct nfp_cpp * cpp,uint32_t model)42 nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
43 {
44 cpp->model = model;
45 }
46
47 uint32_t
nfp_cpp_model(struct nfp_cpp * cpp)48 nfp_cpp_model(struct nfp_cpp *cpp)
49 {
50 int err;
51 uint32_t model;
52
53 if (!cpp)
54 return NFP_CPP_MODEL_INVALID;
55
56 err = __nfp_cpp_model_autodetect(cpp, &model);
57
58 if (err < 0)
59 return err;
60
61 return model;
62 }
63
64 void
nfp_cpp_interface_set(struct nfp_cpp * cpp,uint32_t interface)65 nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface)
66 {
67 cpp->interface = interface;
68 }
69
70 int
nfp_cpp_serial(struct nfp_cpp * cpp,const uint8_t ** serial)71 nfp_cpp_serial(struct nfp_cpp *cpp, const uint8_t **serial)
72 {
73 *serial = cpp->serial;
74 return cpp->serial_len;
75 }
76
77 int
nfp_cpp_serial_set(struct nfp_cpp * cpp,const uint8_t * serial,size_t serial_len)78 nfp_cpp_serial_set(struct nfp_cpp *cpp, const uint8_t *serial,
79 size_t serial_len)
80 {
81 if (cpp->serial_len)
82 free(cpp->serial);
83
84 cpp->serial = malloc(serial_len);
85 if (!cpp->serial)
86 return -1;
87
88 memcpy(cpp->serial, serial, serial_len);
89 cpp->serial_len = serial_len;
90
91 return 0;
92 }
93
94 uint16_t
nfp_cpp_interface(struct nfp_cpp * cpp)95 nfp_cpp_interface(struct nfp_cpp *cpp)
96 {
97 if (!cpp)
98 return NFP_CPP_INTERFACE(NFP_CPP_INTERFACE_TYPE_INVALID, 0, 0);
99
100 return cpp->interface;
101 }
102
103 void *
nfp_cpp_area_priv(struct nfp_cpp_area * cpp_area)104 nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
105 {
106 return &cpp_area[1];
107 }
108
109 struct nfp_cpp *
nfp_cpp_area_cpp(struct nfp_cpp_area * cpp_area)110 nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
111 {
112 return cpp_area->cpp;
113 }
114
115 const char *
nfp_cpp_area_name(struct nfp_cpp_area * cpp_area)116 nfp_cpp_area_name(struct nfp_cpp_area *cpp_area)
117 {
118 return cpp_area->name;
119 }
120
121 /*
122 * nfp_cpp_area_alloc - allocate a new CPP area
123 * @cpp: CPP handle
124 * @dest: CPP id
125 * @address: start address on CPP target
126 * @size: size of area in bytes
127 *
128 * Allocate and initialize a CPP area structure. The area must later
129 * be locked down with an 'acquire' before it can be safely accessed.
130 *
131 * NOTE: @address and @size must be 32-bit aligned values.
132 */
133 struct nfp_cpp_area *
nfp_cpp_area_alloc_with_name(struct nfp_cpp * cpp,uint32_t dest,const char * name,unsigned long long address,unsigned long size)134 nfp_cpp_area_alloc_with_name(struct nfp_cpp *cpp, uint32_t dest,
135 const char *name, unsigned long long address,
136 unsigned long size)
137 {
138 struct nfp_cpp_area *area;
139 uint64_t tmp64 = (uint64_t)address;
140 int tmp, err;
141
142 if (!cpp)
143 return NULL;
144
145 /* CPP bus uses only a 40-bit address */
146 if ((address + size) > (1ULL << 40))
147 return NFP_ERRPTR(EFAULT);
148
149 /* Remap from cpp_island to cpp_target */
150 err = nfp_target_cpp(dest, tmp64, &dest, &tmp64, cpp->imb_cat_table);
151 if (err < 0)
152 return NULL;
153
154 address = (unsigned long long)tmp64;
155
156 if (!name)
157 name = "";
158
159 area = calloc(1, sizeof(*area) + cpp->op->area_priv_size +
160 strlen(name) + 1);
161 if (!area)
162 return NULL;
163
164 area->cpp = cpp;
165 area->name = ((char *)area) + sizeof(*area) + cpp->op->area_priv_size;
166 memcpy(area->name, name, strlen(name) + 1);
167
168 /*
169 * Preserve errno around the call to area_init, since most
170 * implementations will blindly call nfp_target_action_width()for both
171 * read or write modes, and that will set errno to EINVAL.
172 */
173 tmp = errno;
174
175 err = cpp->op->area_init(area, dest, address, size);
176 if (err < 0) {
177 free(area);
178 return NULL;
179 }
180
181 /* Restore errno */
182 errno = tmp;
183
184 area->offset = address;
185 area->size = size;
186
187 return area;
188 }
189
190 struct nfp_cpp_area *
nfp_cpp_area_alloc(struct nfp_cpp * cpp,uint32_t dest,unsigned long long address,unsigned long size)191 nfp_cpp_area_alloc(struct nfp_cpp *cpp, uint32_t dest,
192 unsigned long long address, unsigned long size)
193 {
194 return nfp_cpp_area_alloc_with_name(cpp, dest, NULL, address, size);
195 }
196
197 /*
198 * nfp_cpp_area_alloc_acquire - allocate a new CPP area and lock it down
199 *
200 * @cpp: CPP handle
201 * @dest: CPP id
202 * @address: start address on CPP target
203 * @size: size of area
204 *
205 * Allocate and initialize a CPP area structure, and lock it down so
206 * that it can be accessed directly.
207 *
208 * NOTE: @address and @size must be 32-bit aligned values.
209 *
210 * NOTE: The area must also be 'released' when the structure is freed.
211 */
212 struct nfp_cpp_area *
nfp_cpp_area_alloc_acquire(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,unsigned long size)213 nfp_cpp_area_alloc_acquire(struct nfp_cpp *cpp, uint32_t destination,
214 unsigned long long address, unsigned long size)
215 {
216 struct nfp_cpp_area *area;
217
218 area = nfp_cpp_area_alloc(cpp, destination, address, size);
219 if (!area)
220 return NULL;
221
222 if (nfp_cpp_area_acquire(area)) {
223 nfp_cpp_area_free(area);
224 return NULL;
225 }
226
227 return area;
228 }
229
230 /*
231 * nfp_cpp_area_free - free up the CPP area
232 * area: CPP area handle
233 *
234 * Frees up memory resources held by the CPP area.
235 */
236 void
nfp_cpp_area_free(struct nfp_cpp_area * area)237 nfp_cpp_area_free(struct nfp_cpp_area *area)
238 {
239 if (area->cpp->op->area_cleanup)
240 area->cpp->op->area_cleanup(area);
241 free(area);
242 }
243
244 /*
245 * nfp_cpp_area_release_free - release CPP area and free it
246 * area: CPP area handle
247 *
248 * Releases CPP area and frees up memory resources held by the it.
249 */
250 void
nfp_cpp_area_release_free(struct nfp_cpp_area * area)251 nfp_cpp_area_release_free(struct nfp_cpp_area *area)
252 {
253 nfp_cpp_area_release(area);
254 nfp_cpp_area_free(area);
255 }
256
257 /*
258 * nfp_cpp_area_acquire - lock down a CPP area for access
259 * @area: CPP area handle
260 *
261 * Locks down the CPP area for a potential long term activity. Area
262 * must always be locked down before being accessed.
263 */
264 int
nfp_cpp_area_acquire(struct nfp_cpp_area * area)265 nfp_cpp_area_acquire(struct nfp_cpp_area *area)
266 {
267 if (area->cpp->op->area_acquire) {
268 int err = area->cpp->op->area_acquire(area);
269
270 if (err < 0)
271 return -1;
272 }
273
274 return 0;
275 }
276
277 /*
278 * nfp_cpp_area_release - release a locked down CPP area
279 * @area: CPP area handle
280 *
281 * Releases a previously locked down CPP area.
282 */
283 void
nfp_cpp_area_release(struct nfp_cpp_area * area)284 nfp_cpp_area_release(struct nfp_cpp_area *area)
285 {
286 if (area->cpp->op->area_release)
287 area->cpp->op->area_release(area);
288 }
289
290 /*
291 * nfp_cpp_area_iomem() - get IOMEM region for CPP area
292 *
293 * @area: CPP area handle
294 *
295 * Returns an iomem pointer for use with readl()/writel() style operations.
296 *
297 * NOTE: Area must have been locked down with an 'acquire'.
298 *
299 * Return: pointer to the area, or NULL
300 */
301 void *
nfp_cpp_area_iomem(struct nfp_cpp_area * area)302 nfp_cpp_area_iomem(struct nfp_cpp_area *area)
303 {
304 void *iomem = NULL;
305
306 if (area->cpp->op->area_iomem)
307 iomem = area->cpp->op->area_iomem(area);
308
309 return iomem;
310 }
311
312 /*
313 * nfp_cpp_area_read - read data from CPP area
314 *
315 * @area: CPP area handle
316 * @offset: offset into CPP area
317 * @kernel_vaddr: kernel address to put data into
318 * @length: number of bytes to read
319 *
320 * Read data from indicated CPP region.
321 *
322 * NOTE: @offset and @length must be 32-bit aligned values.
323 *
324 * NOTE: Area must have been locked down with an 'acquire'.
325 */
326 int
nfp_cpp_area_read(struct nfp_cpp_area * area,unsigned long offset,void * kernel_vaddr,size_t length)327 nfp_cpp_area_read(struct nfp_cpp_area *area, unsigned long offset,
328 void *kernel_vaddr, size_t length)
329 {
330 if ((offset + length) > area->size)
331 return NFP_ERRNO(EFAULT);
332
333 return area->cpp->op->area_read(area, kernel_vaddr, offset, length);
334 }
335
336 /*
337 * nfp_cpp_area_write - write data to CPP area
338 *
339 * @area: CPP area handle
340 * @offset: offset into CPP area
341 * @kernel_vaddr: kernel address to read data from
342 * @length: number of bytes to write
343 *
344 * Write data to indicated CPP region.
345 *
346 * NOTE: @offset and @length must be 32-bit aligned values.
347 *
348 * NOTE: Area must have been locked down with an 'acquire'.
349 */
350 int
nfp_cpp_area_write(struct nfp_cpp_area * area,unsigned long offset,const void * kernel_vaddr,size_t length)351 nfp_cpp_area_write(struct nfp_cpp_area *area, unsigned long offset,
352 const void *kernel_vaddr, size_t length)
353 {
354 if ((offset + length) > area->size)
355 return NFP_ERRNO(EFAULT);
356
357 return area->cpp->op->area_write(area, kernel_vaddr, offset, length);
358 }
359
360 void *
nfp_cpp_area_mapped(struct nfp_cpp_area * area)361 nfp_cpp_area_mapped(struct nfp_cpp_area *area)
362 {
363 if (area->cpp->op->area_mapped)
364 return area->cpp->op->area_mapped(area);
365 return NULL;
366 }
367
368 /*
369 * nfp_cpp_area_check_range - check if address range fits in CPP area
370 *
371 * @area: CPP area handle
372 * @offset: offset into CPP area
373 * @length: size of address range in bytes
374 *
375 * Check if address range fits within CPP area. Return 0 if area fits
376 * or -1 on error.
377 */
378 int
nfp_cpp_area_check_range(struct nfp_cpp_area * area,unsigned long long offset,unsigned long length)379 nfp_cpp_area_check_range(struct nfp_cpp_area *area, unsigned long long offset,
380 unsigned long length)
381 {
382 if (((offset + length) > area->size))
383 return NFP_ERRNO(EFAULT);
384
385 return 0;
386 }
387
388 /*
389 * Return the correct CPP address, and fixup xpb_addr as needed,
390 * based upon NFP model.
391 */
392 static uint32_t
nfp_xpb_to_cpp(struct nfp_cpp * cpp,uint32_t * xpb_addr)393 nfp_xpb_to_cpp(struct nfp_cpp *cpp, uint32_t *xpb_addr)
394 {
395 uint32_t xpb;
396 int island;
397
398 xpb = NFP_CPP_ID(14, NFP_CPP_ACTION_RW, 0);
399
400 /*
401 * Ensure that non-local XPB accesses go out through the
402 * global XPBM bus.
403 */
404 island = ((*xpb_addr) >> 24) & 0x3f;
405
406 if (!island)
407 return xpb;
408
409 if (island == 1) {
410 /*
411 * Accesses to the ARM Island overlay uses Island 0
412 * Global Bit
413 */
414 (*xpb_addr) &= ~0x7f000000;
415 if (*xpb_addr < 0x60000)
416 *xpb_addr |= (1 << 30);
417 else
418 /* And only non-ARM interfaces use island id = 1 */
419 if (NFP_CPP_INTERFACE_TYPE_of(nfp_cpp_interface(cpp)) !=
420 NFP_CPP_INTERFACE_TYPE_ARM)
421 *xpb_addr |= (1 << 24);
422 } else {
423 (*xpb_addr) |= (1 << 30);
424 }
425
426 return xpb;
427 }
428
429 int
nfp_cpp_area_readl(struct nfp_cpp_area * area,unsigned long offset,uint32_t * value)430 nfp_cpp_area_readl(struct nfp_cpp_area *area, unsigned long offset,
431 uint32_t *value)
432 {
433 int sz;
434 uint32_t tmp = 0;
435
436 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
437 *value = rte_le_to_cpu_32(tmp);
438
439 return (sz == sizeof(*value)) ? 0 : -1;
440 }
441
442 int
nfp_cpp_area_writel(struct nfp_cpp_area * area,unsigned long offset,uint32_t value)443 nfp_cpp_area_writel(struct nfp_cpp_area *area, unsigned long offset,
444 uint32_t value)
445 {
446 int sz;
447
448 value = rte_cpu_to_le_32(value);
449 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
450 return (sz == sizeof(value)) ? 0 : -1;
451 }
452
453 int
nfp_cpp_area_readq(struct nfp_cpp_area * area,unsigned long offset,uint64_t * value)454 nfp_cpp_area_readq(struct nfp_cpp_area *area, unsigned long offset,
455 uint64_t *value)
456 {
457 int sz;
458 uint64_t tmp = 0;
459
460 sz = nfp_cpp_area_read(area, offset, &tmp, sizeof(tmp));
461 *value = rte_le_to_cpu_64(tmp);
462
463 return (sz == sizeof(*value)) ? 0 : -1;
464 }
465
466 int
nfp_cpp_area_writeq(struct nfp_cpp_area * area,unsigned long offset,uint64_t value)467 nfp_cpp_area_writeq(struct nfp_cpp_area *area, unsigned long offset,
468 uint64_t value)
469 {
470 int sz;
471
472 value = rte_cpu_to_le_64(value);
473 sz = nfp_cpp_area_write(area, offset, &value, sizeof(value));
474
475 return (sz == sizeof(value)) ? 0 : -1;
476 }
477
478 int
nfp_cpp_readl(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint32_t * value)479 nfp_cpp_readl(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
480 uint32_t *value)
481 {
482 int sz;
483 uint32_t tmp;
484
485 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
486 *value = rte_le_to_cpu_32(tmp);
487
488 return (sz == sizeof(*value)) ? 0 : -1;
489 }
490
491 int
nfp_cpp_writel(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint32_t value)492 nfp_cpp_writel(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
493 uint32_t value)
494 {
495 int sz;
496
497 value = rte_cpu_to_le_32(value);
498 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
499
500 return (sz == sizeof(value)) ? 0 : -1;
501 }
502
503 int
nfp_cpp_readq(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint64_t * value)504 nfp_cpp_readq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
505 uint64_t *value)
506 {
507 int sz;
508 uint64_t tmp;
509
510 sz = nfp_cpp_read(cpp, cpp_id, address, &tmp, sizeof(tmp));
511 *value = rte_le_to_cpu_64(tmp);
512
513 return (sz == sizeof(*value)) ? 0 : -1;
514 }
515
516 int
nfp_cpp_writeq(struct nfp_cpp * cpp,uint32_t cpp_id,unsigned long long address,uint64_t value)517 nfp_cpp_writeq(struct nfp_cpp *cpp, uint32_t cpp_id, unsigned long long address,
518 uint64_t value)
519 {
520 int sz;
521
522 value = rte_cpu_to_le_64(value);
523 sz = nfp_cpp_write(cpp, cpp_id, address, &value, sizeof(value));
524
525 return (sz == sizeof(value)) ? 0 : -1;
526 }
527
528 int
nfp_xpb_writel(struct nfp_cpp * cpp,uint32_t xpb_addr,uint32_t value)529 nfp_xpb_writel(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t value)
530 {
531 uint32_t cpp_dest;
532
533 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
534
535 return nfp_cpp_writel(cpp, cpp_dest, xpb_addr, value);
536 }
537
538 int
nfp_xpb_readl(struct nfp_cpp * cpp,uint32_t xpb_addr,uint32_t * value)539 nfp_xpb_readl(struct nfp_cpp *cpp, uint32_t xpb_addr, uint32_t *value)
540 {
541 uint32_t cpp_dest;
542
543 cpp_dest = nfp_xpb_to_cpp(cpp, &xpb_addr);
544
545 return nfp_cpp_readl(cpp, cpp_dest, xpb_addr, value);
546 }
547
548 static struct nfp_cpp *
nfp_cpp_alloc(struct rte_pci_device * dev,int driver_lock_needed)549 nfp_cpp_alloc(struct rte_pci_device *dev, int driver_lock_needed)
550 {
551 const struct nfp_cpp_operations *ops;
552 struct nfp_cpp *cpp;
553 int err;
554
555 ops = nfp_cpp_transport_operations();
556
557 if (!ops || !ops->init)
558 return NFP_ERRPTR(EINVAL);
559
560 cpp = calloc(1, sizeof(*cpp));
561 if (!cpp)
562 return NULL;
563
564 cpp->op = ops;
565 cpp->driver_lock_needed = driver_lock_needed;
566
567 if (cpp->op->init) {
568 err = cpp->op->init(cpp, dev);
569 if (err < 0) {
570 free(cpp);
571 return NULL;
572 }
573 }
574
575 if (NFP_CPP_MODEL_IS_6000(nfp_cpp_model(cpp))) {
576 uint32_t xpbaddr;
577 size_t tgt;
578
579 for (tgt = 0; tgt < ARRAY_SIZE(cpp->imb_cat_table); tgt++) {
580 /* Hardcoded XPB IMB Base, island 0 */
581 xpbaddr = 0x000a0000 + (tgt * 4);
582 err = nfp_xpb_readl(cpp, xpbaddr,
583 (uint32_t *)&cpp->imb_cat_table[tgt]);
584 if (err < 0) {
585 free(cpp);
586 return NULL;
587 }
588 }
589 }
590
591 return cpp;
592 }
593
594 /*
595 * nfp_cpp_free - free the CPP handle
596 * @cpp: CPP handle
597 */
598 void
nfp_cpp_free(struct nfp_cpp * cpp)599 nfp_cpp_free(struct nfp_cpp *cpp)
600 {
601 if (cpp->op && cpp->op->free)
602 cpp->op->free(cpp);
603
604 if (cpp->serial_len)
605 free(cpp->serial);
606
607 free(cpp);
608 }
609
610 struct nfp_cpp *
nfp_cpp_from_device_name(struct rte_pci_device * dev,int driver_lock_needed)611 nfp_cpp_from_device_name(struct rte_pci_device *dev, int driver_lock_needed)
612 {
613 return nfp_cpp_alloc(dev, driver_lock_needed);
614 }
615
616 /*
617 * Modify bits of a 32-bit value from the XPB bus
618 *
619 * @param cpp NFP CPP device handle
620 * @param xpb_tgt XPB target and address
621 * @param mask mask of bits to alter
622 * @param value value to modify
623 *
624 * @return 0 on success, or -1 on failure (and set errno accordingly).
625 */
626 int
nfp_xpb_writelm(struct nfp_cpp * cpp,uint32_t xpb_tgt,uint32_t mask,uint32_t value)627 nfp_xpb_writelm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
628 uint32_t value)
629 {
630 int err;
631 uint32_t tmp;
632
633 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
634 if (err < 0)
635 return err;
636
637 tmp &= ~mask;
638 tmp |= (mask & value);
639 return nfp_xpb_writel(cpp, xpb_tgt, tmp);
640 }
641
642 /*
643 * Modify bits of a 32-bit value from the XPB bus
644 *
645 * @param cpp NFP CPP device handle
646 * @param xpb_tgt XPB target and address
647 * @param mask mask of bits to alter
648 * @param value value to monitor for
649 * @param timeout_us maximum number of us to wait (-1 for forever)
650 *
651 * @return >= 0 on success, or -1 on failure (and set errno accordingly).
652 */
653 int
nfp_xpb_waitlm(struct nfp_cpp * cpp,uint32_t xpb_tgt,uint32_t mask,uint32_t value,int timeout_us)654 nfp_xpb_waitlm(struct nfp_cpp *cpp, uint32_t xpb_tgt, uint32_t mask,
655 uint32_t value, int timeout_us)
656 {
657 uint32_t tmp;
658 int err;
659
660 do {
661 err = nfp_xpb_readl(cpp, xpb_tgt, &tmp);
662 if (err < 0)
663 goto exit;
664
665 if ((tmp & mask) == (value & mask)) {
666 if (timeout_us < 0)
667 timeout_us = 0;
668 break;
669 }
670
671 if (timeout_us < 0)
672 continue;
673
674 timeout_us -= 100;
675 usleep(100);
676 } while (timeout_us >= 0);
677
678 if (timeout_us < 0)
679 err = NFP_ERRNO(ETIMEDOUT);
680 else
681 err = timeout_us;
682
683 exit:
684 return err;
685 }
686
687 /*
688 * nfp_cpp_read - read from CPP target
689 * @cpp: CPP handle
690 * @destination: CPP id
691 * @address: offset into CPP target
692 * @kernel_vaddr: kernel buffer for result
693 * @length: number of bytes to read
694 */
695 int
nfp_cpp_read(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,void * kernel_vaddr,size_t length)696 nfp_cpp_read(struct nfp_cpp *cpp, uint32_t destination,
697 unsigned long long address, void *kernel_vaddr, size_t length)
698 {
699 struct nfp_cpp_area *area;
700 int err;
701
702 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
703 if (!area) {
704 printf("Area allocation/acquire failed\n");
705 return -1;
706 }
707
708 err = nfp_cpp_area_read(area, 0, kernel_vaddr, length);
709
710 nfp_cpp_area_release_free(area);
711 return err;
712 }
713
714 /*
715 * nfp_cpp_write - write to CPP target
716 * @cpp: CPP handle
717 * @destination: CPP id
718 * @address: offset into CPP target
719 * @kernel_vaddr: kernel buffer to read from
720 * @length: number of bytes to write
721 */
722 int
nfp_cpp_write(struct nfp_cpp * cpp,uint32_t destination,unsigned long long address,const void * kernel_vaddr,size_t length)723 nfp_cpp_write(struct nfp_cpp *cpp, uint32_t destination,
724 unsigned long long address, const void *kernel_vaddr,
725 size_t length)
726 {
727 struct nfp_cpp_area *area;
728 int err;
729
730 area = nfp_cpp_area_alloc_acquire(cpp, destination, address, length);
731 if (!area)
732 return -1;
733
734 err = nfp_cpp_area_write(area, 0, kernel_vaddr, length);
735
736 nfp_cpp_area_release_free(area);
737 return err;
738 }
739
740 /*
741 * nfp_cpp_area_fill - fill a CPP area with a value
742 * @area: CPP area
743 * @offset: offset into CPP area
744 * @value: value to fill with
745 * @length: length of area to fill
746 */
747 int
nfp_cpp_area_fill(struct nfp_cpp_area * area,unsigned long offset,uint32_t value,size_t length)748 nfp_cpp_area_fill(struct nfp_cpp_area *area, unsigned long offset,
749 uint32_t value, size_t length)
750 {
751 int err;
752 size_t i;
753 uint64_t value64;
754
755 value = rte_cpu_to_le_32(value);
756 value64 = ((uint64_t)value << 32) | value;
757
758 if ((offset + length) > area->size)
759 return NFP_ERRNO(EINVAL);
760
761 if ((area->offset + offset) & 3)
762 return NFP_ERRNO(EINVAL);
763
764 if (((area->offset + offset) & 7) == 4 && length >= 4) {
765 err = nfp_cpp_area_write(area, offset, &value, sizeof(value));
766 if (err < 0)
767 return err;
768 if (err != sizeof(value))
769 return NFP_ERRNO(ENOSPC);
770 offset += sizeof(value);
771 length -= sizeof(value);
772 }
773
774 for (i = 0; (i + sizeof(value)) < length; i += sizeof(value64)) {
775 err =
776 nfp_cpp_area_write(area, offset + i, &value64,
777 sizeof(value64));
778 if (err < 0)
779 return err;
780 if (err != sizeof(value64))
781 return NFP_ERRNO(ENOSPC);
782 }
783
784 if ((i + sizeof(value)) <= length) {
785 err =
786 nfp_cpp_area_write(area, offset + i, &value, sizeof(value));
787 if (err < 0)
788 return err;
789 if (err != sizeof(value))
790 return NFP_ERRNO(ENOSPC);
791 i += sizeof(value);
792 }
793
794 return (int)i;
795 }
796
797 /*
798 * NOTE: This code should not use nfp_xpb_* functions,
799 * as those are model-specific
800 */
801 uint32_t
__nfp_cpp_model_autodetect(struct nfp_cpp * cpp,uint32_t * model)802 __nfp_cpp_model_autodetect(struct nfp_cpp *cpp, uint32_t *model)
803 {
804 uint32_t reg;
805 int err;
806
807 err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
808 ®);
809 if (err < 0)
810 return err;
811
812 *model = reg & NFP_PL_DEVICE_MODEL_MASK;
813 if (*model & NFP_PL_DEVICE_ID_MASK)
814 *model -= 0x10;
815
816 return 0;
817 }
818
819 /*
820 * nfp_cpp_map_area() - Helper function to map an area
821 * @cpp: NFP CPP handler
822 * @domain: CPP domain
823 * @target: CPP target
824 * @addr: CPP address
825 * @size: Size of the area
826 * @area: Area handle (output)
827 *
828 * Map an area of IOMEM access. To undo the effect of this function call
829 * @nfp_cpp_area_release_free(*area).
830 *
831 * Return: Pointer to memory mapped area or ERR_PTR
832 */
833 uint8_t *
nfp_cpp_map_area(struct nfp_cpp * cpp,int domain,int target,uint64_t addr,unsigned long size,struct nfp_cpp_area ** area)834 nfp_cpp_map_area(struct nfp_cpp *cpp, int domain, int target, uint64_t addr,
835 unsigned long size, struct nfp_cpp_area **area)
836 {
837 uint8_t *res;
838 uint32_t dest;
839
840 dest = NFP_CPP_ISLAND_ID(target, NFP_CPP_ACTION_RW, 0, domain);
841
842 *area = nfp_cpp_area_alloc_acquire(cpp, dest, addr, size);
843 if (!*area)
844 goto err_eio;
845
846 res = nfp_cpp_area_iomem(*area);
847 if (!res)
848 goto err_release_free;
849
850 return res;
851
852 err_release_free:
853 nfp_cpp_area_release_free(*area);
854 err_eio:
855 return NULL;
856 }
857