net/softnic: fix memory leak as profile is freed
[dpdk.git] / drivers / net / nfp / nfpcore / nfp_cppcore.c
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
30 nfp_cpp_priv_set(struct nfp_cpp *cpp, void *priv)
31 {
32         cpp->priv = priv;
33 }
34
35 void *
36 nfp_cpp_priv(struct nfp_cpp *cpp)
37 {
38         return cpp->priv;
39 }
40
41 void
42 nfp_cpp_model_set(struct nfp_cpp *cpp, uint32_t model)
43 {
44         cpp->model = model;
45 }
46
47 uint32_t
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
65 nfp_cpp_interface_set(struct nfp_cpp *cpp, uint32_t interface)
66 {
67         cpp->interface = interface;
68 }
69
70 int
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
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
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 *
104 nfp_cpp_area_priv(struct nfp_cpp_area *cpp_area)
105 {
106         return &cpp_area[1];
107 }
108
109 struct nfp_cpp *
110 nfp_cpp_area_cpp(struct nfp_cpp_area *cpp_area)
111 {
112         return cpp_area->cpp;
113 }
114
115 const char *
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 *
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 *
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 initilizae 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 *
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
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
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
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
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 *
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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
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 *
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
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
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
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
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
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
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                             &reg);
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 *
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 }