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