xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision 600f6d2c770499ad38c51993da8ea59dac6ac7d3)
119af5a38SHeinrich Kuhn /* SPDX-License-Identifier: BSD-3-Clause
219af5a38SHeinrich Kuhn  * Copyright (c) 2014-2021 Netronome Systems, Inc.
319af5a38SHeinrich Kuhn  * All rights reserved.
419af5a38SHeinrich Kuhn  */
519af5a38SHeinrich Kuhn 
6f1523facSChaoyong He #include "nfp_cpp_bridge.h"
7f1523facSChaoyong He 
88987de81SChaoyong He #include <unistd.h>
98987de81SChaoyong He #include <sys/ioctl.h>
108987de81SChaoyong He 
1119af5a38SHeinrich Kuhn #include "nfpcore/nfp_cpp.h"
128d7a59f1SHeinrich Kuhn #include "nfp_logs.h"
13*600f6d2cSLong Wu #include "nfp_service.h"
14f1523facSChaoyong He 
15f1523facSChaoyong He #define NFP_CPP_MEMIO_BOUNDARY    (1 << 20)
16f1523facSChaoyong He #define NFP_BRIDGE_OP_READ        20
17f1523facSChaoyong He #define NFP_BRIDGE_OP_WRITE       30
18f1523facSChaoyong He #define NFP_BRIDGE_OP_IOCTL       40
19f1523facSChaoyong He 
20f1523facSChaoyong He #define NFP_IOCTL 'n'
21f1523facSChaoyong He #define NFP_IOCTL_CPP_IDENTIFICATION _IOW(NFP_IOCTL, 0x8f, uint32_t)
2219af5a38SHeinrich Kuhn 
2319af5a38SHeinrich Kuhn /* Prototypes */
24b1880421SChaoyong He static int nfp_cpp_bridge_service_func(void *args);
2519af5a38SHeinrich Kuhn 
26b1880421SChaoyong He int
27bab0e6f4SChaoyong He nfp_enable_cpp_service(struct nfp_pf_dev *pf_dev)
28b1880421SChaoyong He {
29b1880421SChaoyong He 	int ret;
30*600f6d2cSLong Wu 	const char *pci_name;
31b1880421SChaoyong He 	struct rte_service_spec cpp_service = {
32b1880421SChaoyong He 		.callback          = nfp_cpp_bridge_service_func,
33*600f6d2cSLong Wu 		.callback_userdata = (void *)pf_dev,
34b1880421SChaoyong He 	};
35b1880421SChaoyong He 
36*600f6d2cSLong Wu 	pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
37*600f6d2cSLong Wu 	snprintf(cpp_service.name, sizeof(cpp_service.name), "%s_cpp_service", pci_name);
38b1880421SChaoyong He 
39*600f6d2cSLong Wu 	ret = nfp_service_enable(&cpp_service, &pf_dev->cpp_service_info);
40b1880421SChaoyong He 	if (ret != 0) {
41*600f6d2cSLong Wu 		PMD_INIT_LOG(DEBUG, "Could not enable service %s", cpp_service.name);
42*600f6d2cSLong Wu 		return ret;
43b1880421SChaoyong He 	}
44b1880421SChaoyong He 
45b1880421SChaoyong He 	return 0;
4619af5a38SHeinrich Kuhn }
4719af5a38SHeinrich Kuhn 
4819af5a38SHeinrich Kuhn /*
4919af5a38SHeinrich Kuhn  * Serving a write request to NFP from host programs. The request
5019af5a38SHeinrich Kuhn  * sends the write size and the CPP target. The bridge makes use
5119af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup.
5219af5a38SHeinrich Kuhn  */
5319af5a38SHeinrich Kuhn static int
54f4d24fe9SChaoyong He nfp_cpp_bridge_serve_write(int sockfd,
55f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
5619af5a38SHeinrich Kuhn {
5749952141SChaoyong He 	int err;
5849952141SChaoyong He 	off_t offset;
5949952141SChaoyong He 	uint32_t pos;
6049952141SChaoyong He 	uint32_t len;
6149952141SChaoyong He 	size_t count;
6249952141SChaoyong He 	size_t curlen;
6349952141SChaoyong He 	uint32_t cpp_id;
6449952141SChaoyong He 	off_t nfp_offset;
6519af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
6649952141SChaoyong He 	struct nfp_cpp_area *area;
6719af5a38SHeinrich Kuhn 
68030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu", __func__,
6919af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
7019af5a38SHeinrich Kuhn 
7119af5a38SHeinrich Kuhn 	/* Reading the count param */
7219af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
7319af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
7419af5a38SHeinrich Kuhn 		return -EINVAL;
7519af5a38SHeinrich Kuhn 
7619af5a38SHeinrich Kuhn 	curlen = count;
7719af5a38SHeinrich Kuhn 
7819af5a38SHeinrich Kuhn 	/* Reading the offset param */
7919af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
8019af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
8119af5a38SHeinrich Kuhn 		return -EINVAL;
8219af5a38SHeinrich Kuhn 
8319af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
8419af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
8519af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
8619af5a38SHeinrich Kuhn 
87030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd", __func__, count,
8819af5a38SHeinrich Kuhn 			offset);
89030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd", __func__,
9019af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
9119af5a38SHeinrich Kuhn 
9219af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
9319af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
9419af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
9519af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
9619af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
9719af5a38SHeinrich Kuhn 	}
9819af5a38SHeinrich Kuhn 
9919af5a38SHeinrich Kuhn 	while (count > 0) {
100030b2b19SChaoyong He 		/* Configure a CPP PCIe2CPP BAR for mapping the CPP target */
10119af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
10219af5a38SHeinrich Kuhn 				nfp_offset, curlen);
103cbcbfd73SJames Hershaw 		if (area == NULL) {
10454fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc fail");
10519af5a38SHeinrich Kuhn 			return -EIO;
10619af5a38SHeinrich Kuhn 		}
10719af5a38SHeinrich Kuhn 
108030b2b19SChaoyong He 		/* Mapping the target */
10919af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
11019af5a38SHeinrich Kuhn 		if (err < 0) {
11154fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
11219af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
11319af5a38SHeinrich Kuhn 			return -EIO;
11419af5a38SHeinrich Kuhn 		}
11519af5a38SHeinrich Kuhn 
11619af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
11719af5a38SHeinrich Kuhn 			len = curlen - pos;
11819af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
11919af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
12019af5a38SHeinrich Kuhn 
121030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu", __func__,
12219af5a38SHeinrich Kuhn 					len, count);
12319af5a38SHeinrich Kuhn 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
12419af5a38SHeinrich Kuhn 			if (err != (int)len) {
125f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when receiving, %d of %zu",
12654fdb550SChaoyong He 						err, count);
12719af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
12819af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
12919af5a38SHeinrich Kuhn 				return -EIO;
13019af5a38SHeinrich Kuhn 			}
131b0c496abSChaoyong He 
13219af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
13319af5a38SHeinrich Kuhn 			if (err < 0) {
13454fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_write error");
13519af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
13619af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
13719af5a38SHeinrich Kuhn 				return -EIO;
13819af5a38SHeinrich Kuhn 			}
13919af5a38SHeinrich Kuhn 		}
14019af5a38SHeinrich Kuhn 
14119af5a38SHeinrich Kuhn 		nfp_offset += pos;
14219af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
14319af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
14419af5a38SHeinrich Kuhn 
14519af5a38SHeinrich Kuhn 		count -= pos;
14619af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
14719af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
14819af5a38SHeinrich Kuhn 	}
14919af5a38SHeinrich Kuhn 
15019af5a38SHeinrich Kuhn 	return 0;
15119af5a38SHeinrich Kuhn }
15219af5a38SHeinrich Kuhn 
15319af5a38SHeinrich Kuhn /*
15419af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
15519af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
15619af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
15719af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
15819af5a38SHeinrich Kuhn  */
15919af5a38SHeinrich Kuhn static int
160f4d24fe9SChaoyong He nfp_cpp_bridge_serve_read(int sockfd,
161f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
16219af5a38SHeinrich Kuhn {
16349952141SChaoyong He 	int err;
16449952141SChaoyong He 	off_t offset;
16549952141SChaoyong He 	uint32_t pos;
16649952141SChaoyong He 	uint32_t len;
16749952141SChaoyong He 	size_t count;
16849952141SChaoyong He 	size_t curlen;
16949952141SChaoyong He 	uint32_t cpp_id;
17049952141SChaoyong He 	off_t nfp_offset;
17119af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
17249952141SChaoyong He 	struct nfp_cpp_area *area;
17319af5a38SHeinrich Kuhn 
174030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu", __func__,
17519af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
17619af5a38SHeinrich Kuhn 
17719af5a38SHeinrich Kuhn 	/* Reading the count param */
17819af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
17919af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
18019af5a38SHeinrich Kuhn 		return -EINVAL;
18119af5a38SHeinrich Kuhn 
18219af5a38SHeinrich Kuhn 	curlen = count;
18319af5a38SHeinrich Kuhn 
18419af5a38SHeinrich Kuhn 	/* Reading the offset param */
18519af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
18619af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
18719af5a38SHeinrich Kuhn 		return -EINVAL;
18819af5a38SHeinrich Kuhn 
18919af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
19019af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
19119af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
19219af5a38SHeinrich Kuhn 
193030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd", __func__, count,
19419af5a38SHeinrich Kuhn 			offset);
195030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd", __func__,
19619af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
19719af5a38SHeinrich Kuhn 
19819af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
19919af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
20019af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
20119af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
20219af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
20319af5a38SHeinrich Kuhn 	}
20419af5a38SHeinrich Kuhn 
20519af5a38SHeinrich Kuhn 	while (count > 0) {
20619af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
20719af5a38SHeinrich Kuhn 				nfp_offset, curlen);
208cbcbfd73SJames Hershaw 		if (area == NULL) {
20954fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc failed");
21019af5a38SHeinrich Kuhn 			return -EIO;
21119af5a38SHeinrich Kuhn 		}
21219af5a38SHeinrich Kuhn 
21319af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
21419af5a38SHeinrich Kuhn 		if (err < 0) {
21554fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
21619af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
21719af5a38SHeinrich Kuhn 			return -EIO;
21819af5a38SHeinrich Kuhn 		}
21919af5a38SHeinrich Kuhn 
22019af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
22119af5a38SHeinrich Kuhn 			len = curlen - pos;
22219af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
22319af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
22419af5a38SHeinrich Kuhn 
22519af5a38SHeinrich Kuhn 			err = nfp_cpp_area_read(area, pos, tmpbuf, len);
22619af5a38SHeinrich Kuhn 			if (err < 0) {
22754fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_read error");
22819af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
22919af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
23019af5a38SHeinrich Kuhn 				return -EIO;
23119af5a38SHeinrich Kuhn 			}
232030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu", __func__,
23319af5a38SHeinrich Kuhn 					len, count);
23419af5a38SHeinrich Kuhn 
23519af5a38SHeinrich Kuhn 			err = send(sockfd, tmpbuf, len, 0);
23619af5a38SHeinrich Kuhn 			if (err != (int)len) {
237f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when sending: %d of %zu",
23854fdb550SChaoyong He 						err, count);
23919af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
24019af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
24119af5a38SHeinrich Kuhn 				return -EIO;
24219af5a38SHeinrich Kuhn 			}
24319af5a38SHeinrich Kuhn 		}
24419af5a38SHeinrich Kuhn 
24519af5a38SHeinrich Kuhn 		nfp_offset += pos;
24619af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
24719af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
24819af5a38SHeinrich Kuhn 
24919af5a38SHeinrich Kuhn 		count -= pos;
25019af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
25119af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
25219af5a38SHeinrich Kuhn 	}
253b0c496abSChaoyong He 
25419af5a38SHeinrich Kuhn 	return 0;
25519af5a38SHeinrich Kuhn }
25619af5a38SHeinrich Kuhn 
25719af5a38SHeinrich Kuhn /*
25819af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
25919af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
26019af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
26119af5a38SHeinrich Kuhn  * does not require any CPP access at all.
26219af5a38SHeinrich Kuhn  */
26319af5a38SHeinrich Kuhn static int
264f4d24fe9SChaoyong He nfp_cpp_bridge_serve_ioctl(int sockfd,
265f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
26619af5a38SHeinrich Kuhn {
26719af5a38SHeinrich Kuhn 	int err;
26849952141SChaoyong He 	uint32_t cmd;
26949952141SChaoyong He 	uint32_t tmp;
27049952141SChaoyong He 	uint32_t ident_size;
27119af5a38SHeinrich Kuhn 
27219af5a38SHeinrich Kuhn 	/* Reading now the IOCTL command */
27319af5a38SHeinrich Kuhn 	err = recv(sockfd, &cmd, 4, 0);
27419af5a38SHeinrich Kuhn 	if (err != 4) {
27554fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
27619af5a38SHeinrich Kuhn 		return -EIO;
27719af5a38SHeinrich Kuhn 	}
27819af5a38SHeinrich Kuhn 
27919af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
28019af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
28154fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "unknown cmd %d", cmd);
28219af5a38SHeinrich Kuhn 		return -EINVAL;
28319af5a38SHeinrich Kuhn 	}
28419af5a38SHeinrich Kuhn 
28519af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
28619af5a38SHeinrich Kuhn 	if (err != 4) {
28754fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
28819af5a38SHeinrich Kuhn 		return -EIO;
28919af5a38SHeinrich Kuhn 	}
29019af5a38SHeinrich Kuhn 
29119af5a38SHeinrich Kuhn 	tmp = nfp_cpp_model(cpp);
29219af5a38SHeinrich Kuhn 
293030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: sending NFP model %08x", __func__, tmp);
29419af5a38SHeinrich Kuhn 
29519af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
29619af5a38SHeinrich Kuhn 	if (err != 4) {
29754fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "error writing to socket");
29819af5a38SHeinrich Kuhn 		return -EIO;
29919af5a38SHeinrich Kuhn 	}
30019af5a38SHeinrich Kuhn 
301ff627b74SChaoyong He 	tmp = nfp_cpp_interface(cpp);
30219af5a38SHeinrich Kuhn 
303030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x", __func__, tmp);
30419af5a38SHeinrich Kuhn 
30519af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
30619af5a38SHeinrich Kuhn 	if (err != 4) {
30754fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "error writing to socket");
30819af5a38SHeinrich Kuhn 		return -EIO;
30919af5a38SHeinrich Kuhn 	}
31019af5a38SHeinrich Kuhn 
31119af5a38SHeinrich Kuhn 	return 0;
31219af5a38SHeinrich Kuhn }
31319af5a38SHeinrich Kuhn 
31419af5a38SHeinrich Kuhn /*
31519af5a38SHeinrich Kuhn  * This is the code to be executed by a service core. The CPP bridge interface
31619af5a38SHeinrich Kuhn  * is based on a unix socket and requests usually received by a kernel char
31719af5a38SHeinrich Kuhn  * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
31819af5a38SHeinrich Kuhn  * can be executed with a wrapper library and LD_LIBRARY being completely
31919af5a38SHeinrich Kuhn  * unaware of the CPP bridge performing the NFP kernel char driver for CPP
32019af5a38SHeinrich Kuhn  * accesses.
32119af5a38SHeinrich Kuhn  */
322b1880421SChaoyong He static int
32319af5a38SHeinrich Kuhn nfp_cpp_bridge_service_func(void *args)
32419af5a38SHeinrich Kuhn {
32549952141SChaoyong He 	int op;
32649952141SChaoyong He 	int ret;
32749952141SChaoyong He 	int sockfd;
32849952141SChaoyong He 	int datafd;
329bab0e6f4SChaoyong He 	struct nfp_cpp *cpp;
330*600f6d2cSLong Wu 	const char *pci_name;
331*600f6d2cSLong Wu 	char socket_handle[14];
33249952141SChaoyong He 	struct sockaddr address;
333bab0e6f4SChaoyong He 	struct nfp_pf_dev *pf_dev;
334a5b876a5SChaoyong He 	struct timeval timeout = {1, 0};
33519af5a38SHeinrich Kuhn 
336*600f6d2cSLong Wu 	pf_dev = args;
337b0c496abSChaoyong He 
338*600f6d2cSLong Wu 	pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
339*600f6d2cSLong Wu 	snprintf(socket_handle, sizeof(socket_handle), "/tmp/%s", pci_name);
340*600f6d2cSLong Wu 
341*600f6d2cSLong Wu 	unlink(socket_handle);
34219af5a38SHeinrich Kuhn 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
34319af5a38SHeinrich Kuhn 	if (sockfd < 0) {
34454fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "socket creation error. Service failed");
34519af5a38SHeinrich Kuhn 		return -EIO;
34619af5a38SHeinrich Kuhn 	}
34719af5a38SHeinrich Kuhn 
348a5b876a5SChaoyong He 	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
349a5b876a5SChaoyong He 
35019af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
35119af5a38SHeinrich Kuhn 
35219af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
353*600f6d2cSLong Wu 	strcpy(address.sa_data, socket_handle);
35419af5a38SHeinrich Kuhn 
35519af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
35619af5a38SHeinrich Kuhn 			sizeof(struct sockaddr));
35719af5a38SHeinrich Kuhn 	if (ret < 0) {
35854fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "bind error (%d). Service failed", errno);
35919af5a38SHeinrich Kuhn 		close(sockfd);
36019af5a38SHeinrich Kuhn 		return ret;
36119af5a38SHeinrich Kuhn 	}
36219af5a38SHeinrich Kuhn 
36319af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
36419af5a38SHeinrich Kuhn 	if (ret < 0) {
36554fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "listen error(%d). Service failed", errno);
36619af5a38SHeinrich Kuhn 		close(sockfd);
36719af5a38SHeinrich Kuhn 		return ret;
36819af5a38SHeinrich Kuhn 	}
36919af5a38SHeinrich Kuhn 
370bab0e6f4SChaoyong He 	cpp = pf_dev->cpp;
371*600f6d2cSLong Wu 	while (rte_service_runstate_get(pf_dev->cpp_service_info.id) != 0) {
37219af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
37319af5a38SHeinrich Kuhn 		if (datafd < 0) {
374a5b876a5SChaoyong He 			if (errno == EAGAIN || errno == EWOULDBLOCK)
375a5b876a5SChaoyong He 				continue;
376a5b876a5SChaoyong He 
37754fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "accept call error (%d)", errno);
37854fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "service failed");
37919af5a38SHeinrich Kuhn 			close(sockfd);
38019af5a38SHeinrich Kuhn 			return -EIO;
38119af5a38SHeinrich Kuhn 		}
38219af5a38SHeinrich Kuhn 
383e7978635SChaoyong He 		for (;;) {
38419af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
38519af5a38SHeinrich Kuhn 			if (ret <= 0) {
386030b2b19SChaoyong He 				PMD_CPP_LOG(DEBUG, "%s: socket close", __func__);
38719af5a38SHeinrich Kuhn 				break;
38819af5a38SHeinrich Kuhn 			}
38919af5a38SHeinrich Kuhn 
390030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: getting op %u", __func__, op);
39119af5a38SHeinrich Kuhn 
39219af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
39319af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
39419af5a38SHeinrich Kuhn 
39519af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
39619af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
39719af5a38SHeinrich Kuhn 
39819af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
39919af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
40019af5a38SHeinrich Kuhn 
40119af5a38SHeinrich Kuhn 			if (op == 0)
40219af5a38SHeinrich Kuhn 				break;
40319af5a38SHeinrich Kuhn 		}
404b0c496abSChaoyong He 
40519af5a38SHeinrich Kuhn 		close(datafd);
40619af5a38SHeinrich Kuhn 	}
407b0c496abSChaoyong He 
40819af5a38SHeinrich Kuhn 	close(sockfd);
40919af5a38SHeinrich Kuhn 
41019af5a38SHeinrich Kuhn 	return 0;
41119af5a38SHeinrich Kuhn }
412