net/bnxt: fix RSS action
[dpdk.git] / drivers / net / nfp / nfpcore / nfp_cpp_pcie_ops.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Netronome Systems, Inc.
3  * All rights reserved.
4  */
5
6 /*
7  * nfp_cpp_pcie_ops.c
8  * Authors: Vinayak Tammineedi <vinayak.tammineedi@netronome.com>
9  *
10  * Multiplexes the NFP BARs between NFP internal resources and
11  * implements the PCIe specific interface for generic CPP bus access.
12  *
13  * The BARs are managed and allocated if they are available.
14  * The generic CPP bus abstraction builds upon this BAR interface.
15  */
16
17 #include <assert.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdint.h>
22 #include <stdbool.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <dirent.h>
27 #include <libgen.h>
28
29 #include <sys/mman.h>
30 #include <sys/file.h>
31 #include <sys/stat.h>
32
33 #include <ethdev_pci.h>
34 #include <rte_string_fns.h>
35
36 #include "nfp_cpp.h"
37 #include "nfp_target.h"
38 #include "nfp6000/nfp6000.h"
39
40 #define NFP_PCIE_BAR(_pf)       (0x30000 + ((_pf) & 7) * 0xc0)
41
42 #define NFP_PCIE_BAR_PCIE2CPP_ACTION_BASEADDRESS(_x)  (((_x) & 0x1f) << 16)
43 #define NFP_PCIE_BAR_PCIE2CPP_BASEADDRESS(_x)         (((_x) & 0xffff) << 0)
44 #define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT(_x)        (((_x) & 0x3) << 27)
45 #define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_32BIT    0
46 #define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_64BIT    1
47 #define NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_0BYTE    3
48 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE(_x)             (((_x) & 0x7) << 29)
49 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_OF(_x)          (((_x) >> 29) & 0x7)
50 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_FIXED         0
51 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_BULK          1
52 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_TARGET        2
53 #define NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_GENERAL       3
54 #define NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(_x)  (((_x) & 0xf) << 23)
55 #define NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(_x)   (((_x) & 0x3) << 21)
56
57 /*
58  * Minimal size of the PCIe cfg memory we depend on being mapped,
59  * queue controller and DMA controller don't have to be covered.
60  */
61 #define NFP_PCI_MIN_MAP_SIZE                            0x080000
62
63 #define NFP_PCIE_P2C_FIXED_SIZE(bar)               (1 << (bar)->bitsize)
64 #define NFP_PCIE_P2C_BULK_SIZE(bar)                (1 << (bar)->bitsize)
65 #define NFP_PCIE_P2C_GENERAL_TARGET_OFFSET(bar, x) ((x) << ((bar)->bitsize - 2))
66 #define NFP_PCIE_P2C_GENERAL_TOKEN_OFFSET(bar, x) ((x) << ((bar)->bitsize - 4))
67 #define NFP_PCIE_P2C_GENERAL_SIZE(bar)             (1 << ((bar)->bitsize - 4))
68
69 #define NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(bar, slot) \
70         (NFP_PCIE_BAR(0) + ((bar) * 8 + (slot)) * 4)
71
72 #define NFP_PCIE_CPP_BAR_PCIETOCPPEXPBAR(bar, slot) \
73         (((bar) * 8 + (slot)) * 4)
74
75 /*
76  * Define to enable a bit more verbose debug output.
77  * Set to 1 to enable a bit more verbose debug output.
78  */
79 struct nfp_pcie_user;
80 struct nfp6000_area_priv;
81
82 /*
83  * struct nfp_bar - describes BAR configuration and usage
84  * @nfp:        backlink to owner
85  * @barcfg:     cached contents of BAR config CSR
86  * @base:       the BAR's base CPP offset
87  * @mask:       mask for the BAR aperture (read only)
88  * @bitsize:    bitsize of BAR aperture (read only)
89  * @index:      index of the BAR
90  * @lock:       lock to specify if bar is in use
91  * @refcnt:     number of current users
92  * @iomem:      mapped IO memory
93  */
94 #define NFP_BAR_MAX 7
95 struct nfp_bar {
96         struct nfp_pcie_user *nfp;
97         uint32_t barcfg;
98         uint64_t base;          /* CPP address base */
99         uint64_t mask;          /* Bit mask of the bar */
100         uint32_t bitsize;       /* Bit size of the bar */
101         int index;
102         int lock;
103
104         char *csr;
105         char *iomem;
106 };
107
108 #define BUSDEV_SZ       13
109 struct nfp_pcie_user {
110         struct nfp_bar bar[NFP_BAR_MAX];
111
112         int device;
113         int lock;
114         int secondary_lock;
115         char busdev[BUSDEV_SZ];
116         int barsz;
117         char *cfg;
118 };
119
120 static uint32_t
121 nfp_bar_maptype(struct nfp_bar *bar)
122 {
123         return NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_OF(bar->barcfg);
124 }
125
126 #define TARGET_WIDTH_32    4
127 #define TARGET_WIDTH_64    8
128
129 static int
130 nfp_compute_bar(const struct nfp_bar *bar, uint32_t *bar_config,
131                 uint64_t *bar_base, int tgt, int act, int tok,
132                 uint64_t offset, size_t size, int width)
133 {
134         uint32_t bitsize;
135         uint32_t newcfg;
136         uint64_t mask;
137
138         if (tgt >= 16)
139                 return -EINVAL;
140
141         switch (width) {
142         case 8:
143                 newcfg =
144                     NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT
145                     (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_64BIT);
146                 break;
147         case 4:
148                 newcfg =
149                     NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT
150                     (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_32BIT);
151                 break;
152         case 0:
153                 newcfg =
154                     NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT
155                     (NFP_PCIE_BAR_PCIE2CPP_LENGTHSELECT_0BYTE);
156                 break;
157         default:
158                 return -EINVAL;
159         }
160
161         if (act != NFP_CPP_ACTION_RW && act != 0) {
162                 /* Fixed CPP mapping with specific action */
163                 mask = ~(NFP_PCIE_P2C_FIXED_SIZE(bar) - 1);
164
165                 newcfg |=
166                     NFP_PCIE_BAR_PCIE2CPP_MAPTYPE
167                     (NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_FIXED);
168                 newcfg |= NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(tgt);
169                 newcfg |= NFP_PCIE_BAR_PCIE2CPP_ACTION_BASEADDRESS(act);
170                 newcfg |= NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(tok);
171
172                 if ((offset & mask) != ((offset + size - 1) & mask)) {
173                         printf("BAR%d: Won't use for Fixed mapping\n",
174                                 bar->index);
175                         printf("\t<%#llx,%#llx>, action=%d\n",
176                                 (unsigned long long)offset,
177                                 (unsigned long long)(offset + size), act);
178                         printf("\tBAR too small (0x%llx).\n",
179                                 (unsigned long long)mask);
180                         return -EINVAL;
181                 }
182                 offset &= mask;
183
184 #ifdef DEBUG
185                 printf("BAR%d: Created Fixed mapping\n", bar->index);
186                 printf("\t%d:%d:%d:0x%#llx-0x%#llx>\n", tgt, act, tok,
187                         (unsigned long long)offset,
188                         (unsigned long long)(offset + mask));
189 #endif
190
191                 bitsize = 40 - 16;
192         } else {
193                 mask = ~(NFP_PCIE_P2C_BULK_SIZE(bar) - 1);
194
195                 /* Bulk mapping */
196                 newcfg |=
197                     NFP_PCIE_BAR_PCIE2CPP_MAPTYPE
198                     (NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_BULK);
199
200                 newcfg |= NFP_PCIE_BAR_PCIE2CPP_TARGET_BASEADDRESS(tgt);
201                 newcfg |= NFP_PCIE_BAR_PCIE2CPP_TOKEN_BASEADDRESS(tok);
202
203                 if ((offset & mask) != ((offset + size - 1) & mask)) {
204                         printf("BAR%d: Won't use for bulk mapping\n",
205                                 bar->index);
206                         printf("\t<%#llx,%#llx>\n", (unsigned long long)offset,
207                                 (unsigned long long)(offset + size));
208                         printf("\ttarget=%d, token=%d\n", tgt, tok);
209                         printf("\tBAR too small (%#llx) - (%#llx != %#llx).\n",
210                                 (unsigned long long)mask,
211                                 (unsigned long long)(offset & mask),
212                                 (unsigned long long)(offset + size - 1) & mask);
213
214                         return -EINVAL;
215                 }
216
217                 offset &= mask;
218
219 #ifdef DEBUG
220                 printf("BAR%d: Created bulk mapping %d:x:%d:%#llx-%#llx\n",
221                         bar->index, tgt, tok, (unsigned long long)offset,
222                         (unsigned long long)(offset + ~mask));
223 #endif
224
225                 bitsize = 40 - 21;
226         }
227
228         if (bar->bitsize < bitsize) {
229                 printf("BAR%d: Too small for %d:%d:%d\n", bar->index, tgt, tok,
230                         act);
231                 return -EINVAL;
232         }
233
234         newcfg |= offset >> bitsize;
235
236         if (bar_base)
237                 *bar_base = offset;
238
239         if (bar_config)
240                 *bar_config = newcfg;
241
242         return 0;
243 }
244
245 static int
246 nfp_bar_write(struct nfp_pcie_user *nfp, struct nfp_bar *bar,
247                   uint32_t newcfg)
248 {
249         int base, slot;
250
251         base = bar->index >> 3;
252         slot = bar->index & 7;
253
254         if (!nfp->cfg)
255                 return (-ENOMEM);
256
257         bar->csr = nfp->cfg +
258                    NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(base, slot);
259
260         *(uint32_t *)(bar->csr) = newcfg;
261
262         bar->barcfg = newcfg;
263 #ifdef DEBUG
264         printf("BAR%d: updated to 0x%08x\n", bar->index, newcfg);
265 #endif
266
267         return 0;
268 }
269
270 static int
271 nfp_reconfigure_bar(struct nfp_pcie_user *nfp, struct nfp_bar *bar, int tgt,
272                 int act, int tok, uint64_t offset, size_t size, int width)
273 {
274         uint64_t newbase;
275         uint32_t newcfg;
276         int err;
277
278         err = nfp_compute_bar(bar, &newcfg, &newbase, tgt, act, tok, offset,
279                               size, width);
280         if (err)
281                 return err;
282
283         bar->base = newbase;
284
285         return nfp_bar_write(nfp, bar, newcfg);
286 }
287
288 /*
289  * Map all PCI bars. We assume that the BAR with the PCIe config block is
290  * already mapped.
291  *
292  * BAR0.0: Reserved for General Mapping (for MSI-X access to PCIe SRAM)
293  *
294  *         Halving PCItoCPPBars for primary and secondary processes.
295  *         NFP PMD just requires two fixed slots, one for configuration BAR,
296  *         and another for accessing the hw queues. Another slot is needed
297  *         for setting the link up or down. Secondary processes do not need
298  *         to map the first two slots again, but it requires one slot for
299  *         accessing the link, even if it is not likely the secondary process
300  *         starting the port. This implies a limit of secondary processes
301  *         supported. Due to this requirement and future extensions requiring
302  *         new slots per process, only one secondary process is supported by
303  *         now.
304  */
305 static int
306 nfp_enable_bars(struct nfp_pcie_user *nfp)
307 {
308         struct nfp_bar *bar;
309         int x, start, end;
310
311         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
312                 start = 4;
313                 end = 1;
314         } else {
315                 start = 7;
316                 end = 4;
317         }
318         for (x = start; x > end; x--) {
319                 bar = &nfp->bar[x - 1];
320                 bar->barcfg = 0;
321                 bar->nfp = nfp;
322                 bar->index = x;
323                 bar->mask = (1 << (nfp->barsz - 3)) - 1;
324                 bar->bitsize = nfp->barsz - 3;
325                 bar->base = 0;
326                 bar->iomem = NULL;
327                 bar->lock = 0;
328                 bar->csr = nfp->cfg +
329                            NFP_PCIE_CFG_BAR_PCIETOCPPEXPBAR(bar->index >> 3,
330                                                            bar->index & 7);
331
332                 bar->iomem = nfp->cfg + (bar->index << bar->bitsize);
333         }
334         return 0;
335 }
336
337 static struct nfp_bar *
338 nfp_alloc_bar(struct nfp_pcie_user *nfp)
339 {
340         struct nfp_bar *bar;
341         int x, start, end;
342
343         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
344                 start = 4;
345                 end = 1;
346         } else {
347                 start = 7;
348                 end = 4;
349         }
350         for (x = start; x > end; x--) {
351                 bar = &nfp->bar[x - 1];
352                 if (!bar->lock) {
353                         bar->lock = 1;
354                         return bar;
355                 }
356         }
357         return NULL;
358 }
359
360 static void
361 nfp_disable_bars(struct nfp_pcie_user *nfp)
362 {
363         struct nfp_bar *bar;
364         int x, start, end;
365
366         if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
367                 start = 4;
368                 end = 1;
369         } else {
370                 start = 7;
371                 end = 4;
372         }
373
374         for (x = start; x > end; x--) {
375                 bar = &nfp->bar[x - 1];
376                 if (bar->iomem) {
377                         bar->iomem = NULL;
378                         bar->lock = 0;
379                 }
380         }
381 }
382
383 /*
384  * Generic CPP bus access interface.
385  */
386
387 struct nfp6000_area_priv {
388         struct nfp_bar *bar;
389         uint32_t bar_offset;
390
391         uint32_t target;
392         uint32_t action;
393         uint32_t token;
394         uint64_t offset;
395         struct {
396                 int read;
397                 int write;
398                 int bar;
399         } width;
400         size_t size;
401         char *iomem;
402 };
403
404 static int
405 nfp6000_area_init(struct nfp_cpp_area *area, uint32_t dest,
406                   unsigned long long address, unsigned long size)
407 {
408         struct nfp_pcie_user *nfp = nfp_cpp_priv(nfp_cpp_area_cpp(area));
409         struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area);
410         uint32_t target = NFP_CPP_ID_TARGET_of(dest);
411         uint32_t action = NFP_CPP_ID_ACTION_of(dest);
412         uint32_t token = NFP_CPP_ID_TOKEN_of(dest);
413         int pp, ret = 0;
414
415         pp = nfp6000_target_pushpull(NFP_CPP_ID(target, action, token),
416                                      address);
417         if (pp < 0)
418                 return pp;
419
420         priv->width.read = PUSH_WIDTH(pp);
421         priv->width.write = PULL_WIDTH(pp);
422
423         if (priv->width.read > 0 &&
424             priv->width.write > 0 && priv->width.read != priv->width.write)
425                 return -EINVAL;
426
427         if (priv->width.read > 0)
428                 priv->width.bar = priv->width.read;
429         else
430                 priv->width.bar = priv->width.write;
431
432         priv->bar = nfp_alloc_bar(nfp);
433         if (priv->bar == NULL)
434                 return -ENOMEM;
435
436         priv->target = target;
437         priv->action = action;
438         priv->token = token;
439         priv->offset = address;
440         priv->size = size;
441
442         ret = nfp_reconfigure_bar(nfp, priv->bar, priv->target, priv->action,
443                                   priv->token, priv->offset, priv->size,
444                                   priv->width.bar);
445
446         return ret;
447 }
448
449 static int
450 nfp6000_area_acquire(struct nfp_cpp_area *area)
451 {
452         struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area);
453
454         /* Calculate offset into BAR. */
455         if (nfp_bar_maptype(priv->bar) ==
456             NFP_PCIE_BAR_PCIE2CPP_MAPTYPE_GENERAL) {
457                 priv->bar_offset = priv->offset &
458                         (NFP_PCIE_P2C_GENERAL_SIZE(priv->bar) - 1);
459                 priv->bar_offset +=
460                         NFP_PCIE_P2C_GENERAL_TARGET_OFFSET(priv->bar,
461                                                            priv->target);
462                 priv->bar_offset +=
463                     NFP_PCIE_P2C_GENERAL_TOKEN_OFFSET(priv->bar, priv->token);
464         } else {
465                 priv->bar_offset = priv->offset & priv->bar->mask;
466         }
467
468         /* Must have been too big. Sub-allocate. */
469         if (!priv->bar->iomem)
470                 return (-ENOMEM);
471
472         priv->iomem = priv->bar->iomem + priv->bar_offset;
473
474         return 0;
475 }
476
477 static void *
478 nfp6000_area_mapped(struct nfp_cpp_area *area)
479 {
480         struct nfp6000_area_priv *area_priv = nfp_cpp_area_priv(area);
481
482         if (!area_priv->iomem)
483                 return NULL;
484
485         return area_priv->iomem;
486 }
487
488 static void
489 nfp6000_area_release(struct nfp_cpp_area *area)
490 {
491         struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area);
492         priv->bar->lock = 0;
493         priv->bar = NULL;
494         priv->iomem = NULL;
495 }
496
497 static void *
498 nfp6000_area_iomem(struct nfp_cpp_area *area)
499 {
500         struct nfp6000_area_priv *priv = nfp_cpp_area_priv(area);
501         return priv->iomem;
502 }
503
504 static int
505 nfp6000_area_read(struct nfp_cpp_area *area, void *kernel_vaddr,
506                   unsigned long offset, unsigned int length)
507 {
508         uint64_t *wrptr64 = kernel_vaddr;
509         const volatile uint64_t *rdptr64;
510         struct nfp6000_area_priv *priv;
511         uint32_t *wrptr32 = kernel_vaddr;
512         const volatile uint32_t *rdptr32;
513         int width;
514         unsigned int n;
515         bool is_64;
516
517         priv = nfp_cpp_area_priv(area);
518         rdptr64 = (uint64_t *)(priv->iomem + offset);
519         rdptr32 = (uint32_t *)(priv->iomem + offset);
520
521         if (offset + length > priv->size)
522                 return -EFAULT;
523
524         width = priv->width.read;
525
526         if (width <= 0)
527                 return -EINVAL;
528
529         /* Unaligned? Translate to an explicit access */
530         if ((priv->offset + offset) & (width - 1)) {
531                 printf("aread_read unaligned!!!\n");
532                 return -EINVAL;
533         }
534
535         is_64 = width == TARGET_WIDTH_64;
536
537         /* MU reads via a PCIe2CPP BAR supports 32bit (and other) lengths */
538         if (priv->target == (NFP_CPP_TARGET_ID_MASK & NFP_CPP_TARGET_MU) &&
539             priv->action == NFP_CPP_ACTION_RW) {
540                 is_64 = false;
541         }
542
543         if (is_64) {
544                 if (offset % sizeof(uint64_t) != 0 ||
545                     length % sizeof(uint64_t) != 0)
546                         return -EINVAL;
547         } else {
548                 if (offset % sizeof(uint32_t) != 0 ||
549                     length % sizeof(uint32_t) != 0)
550                         return -EINVAL;
551         }
552
553         if (!priv->bar)
554                 return -EFAULT;
555
556         if (is_64)
557                 for (n = 0; n < length; n += sizeof(uint64_t)) {
558                         *wrptr64 = *rdptr64;
559                         wrptr64++;
560                         rdptr64++;
561                 }
562         else
563                 for (n = 0; n < length; n += sizeof(uint32_t)) {
564                         *wrptr32 = *rdptr32;
565                         wrptr32++;
566                         rdptr32++;
567                 }
568
569         return n;
570 }
571
572 static int
573 nfp6000_area_write(struct nfp_cpp_area *area, const void *kernel_vaddr,
574                    unsigned long offset, unsigned int length)
575 {
576         const uint64_t *rdptr64 = kernel_vaddr;
577         uint64_t *wrptr64;
578         const uint32_t *rdptr32 = kernel_vaddr;
579         struct nfp6000_area_priv *priv;
580         uint32_t *wrptr32;
581         int width;
582         unsigned int n;
583         bool is_64;
584
585         priv = nfp_cpp_area_priv(area);
586         wrptr64 = (uint64_t *)(priv->iomem + offset);
587         wrptr32 = (uint32_t *)(priv->iomem + offset);
588
589         if (offset + length > priv->size)
590                 return -EFAULT;
591
592         width = priv->width.write;
593
594         if (width <= 0)
595                 return -EINVAL;
596
597         /* Unaligned? Translate to an explicit access */
598         if ((priv->offset + offset) & (width - 1))
599                 return -EINVAL;
600
601         is_64 = width == TARGET_WIDTH_64;
602
603         /* MU writes via a PCIe2CPP BAR supports 32bit (and other) lengths */
604         if (priv->target == (NFP_CPP_TARGET_ID_MASK & NFP_CPP_TARGET_MU) &&
605             priv->action == NFP_CPP_ACTION_RW)
606                 is_64 = false;
607
608         if (is_64) {
609                 if (offset % sizeof(uint64_t) != 0 ||
610                     length % sizeof(uint64_t) != 0)
611                         return -EINVAL;
612         } else {
613                 if (offset % sizeof(uint32_t) != 0 ||
614                     length % sizeof(uint32_t) != 0)
615                         return -EINVAL;
616         }
617
618         if (!priv->bar)
619                 return -EFAULT;
620
621         if (is_64)
622                 for (n = 0; n < length; n += sizeof(uint64_t)) {
623                         *wrptr64 = *rdptr64;
624                         wrptr64++;
625                         rdptr64++;
626                 }
627         else
628                 for (n = 0; n < length; n += sizeof(uint32_t)) {
629                         *wrptr32 = *rdptr32;
630                         wrptr32++;
631                         rdptr32++;
632                 }
633
634         return n;
635 }
636
637 #define PCI_DEVICES "/sys/bus/pci/devices"
638
639 static int
640 nfp_acquire_process_lock(struct nfp_pcie_user *desc)
641 {
642         int rc;
643         struct flock lock;
644         char lockname[30];
645
646         memset(&lock, 0, sizeof(lock));
647
648         snprintf(lockname, sizeof(lockname), "/var/lock/nfp_%s", desc->busdev);
649         desc->lock = open(lockname, O_RDWR | O_CREAT, 0666);
650         if (desc->lock < 0)
651                 return desc->lock;
652
653         lock.l_type = F_WRLCK;
654         lock.l_whence = SEEK_SET;
655         rc = -1;
656         while (rc != 0) {
657                 rc = fcntl(desc->lock, F_SETLKW, &lock);
658                 if (rc < 0) {
659                         if (errno != EAGAIN && errno != EACCES) {
660                                 close(desc->lock);
661                                 return rc;
662                         }
663                 }
664         }
665
666         return 0;
667 }
668
669 static int
670 nfp_acquire_secondary_process_lock(struct nfp_pcie_user *desc)
671 {
672         int rc;
673         struct flock lock;
674         const char *lockname = "/.lock_nfp_secondary";
675         char *home_path;
676         char *lockfile;
677
678         memset(&lock, 0, sizeof(lock));
679
680         /*
681          * Using user's home directory. Note this can be called in a DPDK app
682          * being executed as non-root. This is not the case for the previous
683          * function nfp_acquire_process_lock which is invoked only when UIO
684          * driver is used because that implies root user.
685          */
686         home_path = getenv("HOME");
687         lockfile = calloc(strlen(home_path) + strlen(lockname) + 1,
688                           sizeof(char));
689
690         if (!lockfile)
691                 return -ENOMEM;
692
693         strcat(lockfile, home_path);
694         strcat(lockfile, "/.lock_nfp_secondary");
695         desc->secondary_lock = open(lockfile, O_RDWR | O_CREAT | O_NONBLOCK,
696                                     0666);
697         if (desc->secondary_lock < 0) {
698                 RTE_LOG(ERR, PMD, "NFP lock for secondary process failed\n");
699                 free(lockfile);
700                 return desc->secondary_lock;
701         }
702
703         lock.l_type = F_WRLCK;
704         lock.l_whence = SEEK_SET;
705         rc = fcntl(desc->secondary_lock, F_SETLK, &lock);
706         if (rc < 0) {
707                 RTE_LOG(ERR, PMD, "NFP lock for secondary process failed\n");
708                 close(desc->secondary_lock);
709         }
710
711         free(lockfile);
712         return rc;
713 }
714
715 static int
716 nfp6000_set_model(struct rte_pci_device *dev, struct nfp_cpp *cpp)
717 {
718         uint32_t model;
719
720         if (rte_pci_read_config(dev, &model, 4, 0x2e) < 0) {
721                 printf("nfp set model failed\n");
722                 return -1;
723         }
724
725         model  = model << 16;
726         nfp_cpp_model_set(cpp, model);
727
728         return 0;
729 }
730
731 static int
732 nfp6000_set_interface(struct rte_pci_device *dev, struct nfp_cpp *cpp)
733 {
734         uint16_t interface;
735
736         if (rte_pci_read_config(dev, &interface, 2, 0x154) < 0) {
737                 printf("nfp set interface failed\n");
738                 return -1;
739         }
740
741         nfp_cpp_interface_set(cpp, interface);
742
743         return 0;
744 }
745
746 static int
747 nfp6000_set_serial(struct rte_pci_device *dev, struct nfp_cpp *cpp)
748 {
749         uint16_t tmp;
750         uint8_t serial[6];
751         int serial_len = 6;
752         off_t pos;
753
754         pos = rte_pci_find_ext_capability(dev, RTE_PCI_EXT_CAP_ID_DSN);
755         if (pos <= 0) {
756                 printf("PCI_EXT_CAP_ID_DSN not found. nfp set serial failed\n");
757                 return -1;
758         } else {
759                 pos += 6;
760         }
761
762         if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
763                 printf("nfp set serial failed\n");
764                 return -1;
765         }
766
767         serial[4] = (uint8_t)((tmp >> 8) & 0xff);
768         serial[5] = (uint8_t)(tmp & 0xff);
769
770         pos += 2;
771         if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
772                 printf("nfp set serial failed\n");
773                 return -1;
774         }
775
776         serial[2] = (uint8_t)((tmp >> 8) & 0xff);
777         serial[3] = (uint8_t)(tmp & 0xff);
778
779         pos += 2;
780         if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
781                 printf("nfp set serial failed\n");
782                 return -1;
783         }
784
785         serial[0] = (uint8_t)((tmp >> 8) & 0xff);
786         serial[1] = (uint8_t)(tmp & 0xff);
787
788         nfp_cpp_serial_set(cpp, serial, serial_len);
789
790         return 0;
791 }
792
793 static int
794 nfp6000_set_barsz(struct rte_pci_device *dev, struct nfp_pcie_user *desc)
795 {
796         unsigned long tmp;
797         int i = 0;
798
799         tmp = dev->mem_resource[0].len;
800
801         while (tmp >>= 1)
802                 i++;
803
804         desc->barsz = i;
805         return 0;
806 }
807
808 static int
809 nfp6000_init(struct nfp_cpp *cpp, struct rte_pci_device *dev)
810 {
811         int ret = 0;
812         struct nfp_pcie_user *desc;
813
814         desc = malloc(sizeof(*desc));
815         if (!desc)
816                 return -1;
817
818
819         memset(desc->busdev, 0, BUSDEV_SZ);
820         strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev));
821
822         if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
823             cpp->driver_lock_needed) {
824                 ret = nfp_acquire_process_lock(desc);
825                 if (ret)
826                         goto error;
827         }
828
829         /* Just support for one secondary process */
830         if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
831                 ret = nfp_acquire_secondary_process_lock(desc);
832                 if (ret)
833                         goto error;
834         }
835
836         if (nfp6000_set_model(dev, cpp) < 0)
837                 goto error;
838         if (nfp6000_set_interface(dev, cpp) < 0)
839                 goto error;
840         if (nfp6000_set_serial(dev, cpp) < 0)
841                 goto error;
842         if (nfp6000_set_barsz(dev, desc) < 0)
843                 goto error;
844
845         desc->cfg = (char *)dev->mem_resource[0].addr;
846
847         nfp_enable_bars(desc);
848
849         nfp_cpp_priv_set(cpp, desc);
850
851         return 0;
852
853 error:
854         free(desc);
855         return -1;
856 }
857
858 static void
859 nfp6000_free(struct nfp_cpp *cpp)
860 {
861         struct nfp_pcie_user *desc = nfp_cpp_priv(cpp);
862
863         nfp_disable_bars(desc);
864         if (cpp->driver_lock_needed)
865                 close(desc->lock);
866         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
867                 close(desc->secondary_lock);
868         close(desc->device);
869         free(desc);
870 }
871
872 static const struct nfp_cpp_operations nfp6000_pcie_ops = {
873         .init = nfp6000_init,
874         .free = nfp6000_free,
875
876         .area_priv_size = sizeof(struct nfp6000_area_priv),
877         .area_init = nfp6000_area_init,
878         .area_acquire = nfp6000_area_acquire,
879         .area_release = nfp6000_area_release,
880         .area_mapped = nfp6000_area_mapped,
881         .area_read = nfp6000_area_read,
882         .area_write = nfp6000_area_write,
883         .area_iomem = nfp6000_area_iomem,
884 };
885
886 const struct
887 nfp_cpp_operations *nfp_cpp_transport_operations(void)
888 {
889         return &nfp6000_pcie_ops;
890 }