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 <[email protected]>
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
nfp_bar_maptype(struct nfp_bar * bar)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
nfp_compute_bar(const struct nfp_bar * bar,uint32_t * bar_config,uint64_t * bar_base,int tgt,int act,int tok,uint64_t offset,size_t size,int width)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
nfp_bar_write(struct nfp_pcie_user * nfp,struct nfp_bar * bar,uint32_t newcfg)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
nfp_reconfigure_bar(struct nfp_pcie_user * nfp,struct nfp_bar * bar,int tgt,int act,int tok,uint64_t offset,size_t size,int width)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
nfp_enable_bars(struct nfp_pcie_user * nfp)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 *
nfp_alloc_bar(struct nfp_pcie_user * nfp)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
nfp_disable_bars(struct nfp_pcie_user * nfp)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
nfp6000_area_init(struct nfp_cpp_area * area,uint32_t dest,unsigned long long address,unsigned long size)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
nfp6000_area_acquire(struct nfp_cpp_area * area)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 *
nfp6000_area_mapped(struct nfp_cpp_area * area)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
nfp6000_area_release(struct nfp_cpp_area * area)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 *
nfp6000_area_iomem(struct nfp_cpp_area * area)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
nfp6000_area_read(struct nfp_cpp_area * area,void * kernel_vaddr,unsigned long offset,unsigned int length)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
nfp6000_area_write(struct nfp_cpp_area * area,const void * kernel_vaddr,unsigned long offset,unsigned int length)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
nfp_acquire_process_lock(struct nfp_pcie_user * desc)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
nfp_acquire_secondary_process_lock(struct nfp_pcie_user * desc)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
nfp6000_set_model(struct rte_pci_device * dev,struct nfp_cpp * cpp)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
nfp6000_set_interface(struct rte_pci_device * dev,struct nfp_cpp * cpp)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 static int
nfp6000_set_serial(struct rte_pci_device * dev,struct nfp_cpp * cpp)750 nfp6000_set_serial(struct rte_pci_device *dev, struct nfp_cpp *cpp)
751 {
752 	uint16_t tmp;
753 	uint8_t serial[6];
754 	int serial_len = 6;
755 	off_t pos;
756 
757 	pos = rte_pci_find_ext_capability(dev, RTE_PCI_EXT_CAP_ID_DSN);
758 	if (pos <= 0) {
759 		printf("PCI_EXT_CAP_ID_DSN not found. nfp set serial failed\n");
760 		return -1;
761 	} else {
762 		pos += 6;
763 	}
764 
765 	if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
766 		printf("nfp set serial failed\n");
767 		return -1;
768 	}
769 
770 	serial[4] = (uint8_t)((tmp >> 8) & 0xff);
771 	serial[5] = (uint8_t)(tmp & 0xff);
772 
773 	pos += 2;
774 	if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
775 		printf("nfp set serial failed\n");
776 		return -1;
777 	}
778 
779 	serial[2] = (uint8_t)((tmp >> 8) & 0xff);
780 	serial[3] = (uint8_t)(tmp & 0xff);
781 
782 	pos += 2;
783 	if (rte_pci_read_config(dev, &tmp, 2, pos) < 0) {
784 		printf("nfp set serial failed\n");
785 		return -1;
786 	}
787 
788 	serial[0] = (uint8_t)((tmp >> 8) & 0xff);
789 	serial[1] = (uint8_t)(tmp & 0xff);
790 
791 	nfp_cpp_serial_set(cpp, serial, serial_len);
792 
793 	return 0;
794 }
795 
796 static int
nfp6000_set_barsz(struct rte_pci_device * dev,struct nfp_pcie_user * desc)797 nfp6000_set_barsz(struct rte_pci_device *dev, struct nfp_pcie_user *desc)
798 {
799 	unsigned long tmp;
800 	int i = 0;
801 
802 	tmp = dev->mem_resource[0].len;
803 
804 	while (tmp >>= 1)
805 		i++;
806 
807 	desc->barsz = i;
808 	return 0;
809 }
810 
811 static int
nfp6000_init(struct nfp_cpp * cpp,struct rte_pci_device * dev)812 nfp6000_init(struct nfp_cpp *cpp, struct rte_pci_device *dev)
813 {
814 	int ret = 0;
815 	struct nfp_pcie_user *desc;
816 
817 	desc = malloc(sizeof(*desc));
818 	if (!desc)
819 		return -1;
820 
821 
822 	memset(desc->busdev, 0, BUSDEV_SZ);
823 	strlcpy(desc->busdev, dev->device.name, sizeof(desc->busdev));
824 
825 	if (rte_eal_process_type() == RTE_PROC_PRIMARY &&
826 	    cpp->driver_lock_needed) {
827 		ret = nfp_acquire_process_lock(desc);
828 		if (ret)
829 			goto error;
830 	}
831 
832 	/* Just support for one secondary process */
833 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
834 		ret = nfp_acquire_secondary_process_lock(desc);
835 		if (ret)
836 			goto error;
837 	}
838 
839 	if (nfp6000_set_model(dev, cpp) < 0)
840 		goto error;
841 	if (nfp6000_set_interface(dev, cpp) < 0)
842 		goto error;
843 	if (nfp6000_set_serial(dev, cpp) < 0)
844 		goto error;
845 	if (nfp6000_set_barsz(dev, desc) < 0)
846 		goto error;
847 
848 	desc->cfg = (char *)dev->mem_resource[0].addr;
849 
850 	nfp_enable_bars(desc);
851 
852 	nfp_cpp_priv_set(cpp, desc);
853 
854 	return 0;
855 
856 error:
857 	free(desc);
858 	return -1;
859 }
860 
861 static void
nfp6000_free(struct nfp_cpp * cpp)862 nfp6000_free(struct nfp_cpp *cpp)
863 {
864 	struct nfp_pcie_user *desc = nfp_cpp_priv(cpp);
865 
866 	nfp_disable_bars(desc);
867 	if (cpp->driver_lock_needed)
868 		close(desc->lock);
869 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
870 		close(desc->secondary_lock);
871 	close(desc->device);
872 	free(desc);
873 }
874 
875 static const struct nfp_cpp_operations nfp6000_pcie_ops = {
876 	.init = nfp6000_init,
877 	.free = nfp6000_free,
878 
879 	.area_priv_size = sizeof(struct nfp6000_area_priv),
880 	.area_init = nfp6000_area_init,
881 	.area_acquire = nfp6000_area_acquire,
882 	.area_release = nfp6000_area_release,
883 	.area_mapped = nfp6000_area_mapped,
884 	.area_read = nfp6000_area_read,
885 	.area_write = nfp6000_area_write,
886 	.area_iomem = nfp6000_area_iomem,
887 };
888 
889 const struct
nfp_cpp_transport_operations(void)890 nfp_cpp_operations *nfp_cpp_transport_operations(void)
891 {
892 	return &nfp6000_pcie_ops;
893 }
894