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 #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
nfp_bar_maptype(struct nfp_bar * bar)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
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)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
nfp_bar_write(struct nfp_pcie_user * nfp,struct nfp_bar * bar,uint32_t newcfg)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
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)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
nfp_enable_bars(struct nfp_pcie_user * nfp)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 *
nfp_alloc_bar(struct nfp_pcie_user * nfp)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
nfp_disable_bars(struct nfp_pcie_user * nfp)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
nfp6000_area_init(struct nfp_cpp_area * area,uint32_t dest,unsigned long long address,unsigned long size)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
nfp6000_area_acquire(struct nfp_cpp_area * area)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 *
nfp6000_area_mapped(struct nfp_cpp_area * area)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
nfp6000_area_release(struct nfp_cpp_area * area)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 *
nfp6000_area_iomem(struct nfp_cpp_area * area)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
nfp6000_area_read(struct nfp_cpp_area * area,void * kernel_vaddr,unsigned long offset,unsigned int length)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
nfp6000_area_write(struct nfp_cpp_area * area,const void * kernel_vaddr,unsigned long offset,unsigned int length)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
nfp_acquire_process_lock(struct nfp_pcie_user * desc)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
nfp_acquire_secondary_process_lock(struct nfp_pcie_user * desc)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
nfp6000_set_model(struct rte_pci_device * dev,struct nfp_cpp * cpp)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
nfp6000_set_interface(struct rte_pci_device * dev,struct nfp_cpp * cpp)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
nfp6000_set_serial(struct rte_pci_device * dev,struct nfp_cpp * cpp)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
nfp6000_set_barsz(struct rte_pci_device * dev,struct nfp_pcie_user * desc)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
nfp6000_init(struct nfp_cpp * cpp,struct rte_pci_device * dev)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
nfp6000_free(struct nfp_cpp * cpp)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
nfp_cpp_transport_operations(void)887 nfp_cpp_operations *nfp_cpp_transport_operations(void)
888 {
889 	return &nfp6000_pcie_ops;
890 }
891