xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
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"
13600f6d2cSLong 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;
30600f6d2cSLong Wu 	const char *pci_name;
31b1880421SChaoyong He 	struct rte_service_spec cpp_service = {
32b1880421SChaoyong He 		.callback          = nfp_cpp_bridge_service_func,
33600f6d2cSLong Wu 		.callback_userdata = (void *)pf_dev,
34b1880421SChaoyong He 	};
35b1880421SChaoyong He 
36600f6d2cSLong Wu 	pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
37600f6d2cSLong Wu 	snprintf(cpp_service.name, sizeof(cpp_service.name), "%s_cpp_service", pci_name);
38b1880421SChaoyong He 
39600f6d2cSLong Wu 	ret = nfp_service_enable(&cpp_service, &pf_dev->cpp_service_info);
40b1880421SChaoyong He 	if (ret != 0) {
41*b6de4353SZerun Fu 		PMD_INIT_LOG(DEBUG, "Could not enable service %s.", cpp_service.name);
42600f6d2cSLong Wu 		return ret;
43b1880421SChaoyong He 	}
44b1880421SChaoyong He 
45b1880421SChaoyong He 	return 0;
4619af5a38SHeinrich Kuhn }
4719af5a38SHeinrich Kuhn 
48929b0531SLong Wu void
49929b0531SLong Wu nfp_disable_cpp_service(struct nfp_pf_dev *pf_dev)
50929b0531SLong Wu {
51929b0531SLong Wu 	nfp_service_disable(&pf_dev->cpp_service_info);
52929b0531SLong Wu }
53929b0531SLong Wu 
5419af5a38SHeinrich Kuhn /*
5519af5a38SHeinrich Kuhn  * Serving a write request to NFP from host programs. The request
5619af5a38SHeinrich Kuhn  * sends the write size and the CPP target. The bridge makes use
5719af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup.
5819af5a38SHeinrich Kuhn  */
5919af5a38SHeinrich Kuhn static int
60f4d24fe9SChaoyong He nfp_cpp_bridge_serve_write(int sockfd,
61f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
6219af5a38SHeinrich Kuhn {
6349952141SChaoyong He 	int err;
6449952141SChaoyong He 	off_t offset;
6549952141SChaoyong He 	uint32_t pos;
6649952141SChaoyong He 	uint32_t len;
6749952141SChaoyong He 	size_t count;
6849952141SChaoyong He 	size_t curlen;
6949952141SChaoyong He 	uint32_t cpp_id;
7049952141SChaoyong He 	off_t nfp_offset;
7119af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
7249952141SChaoyong He 	struct nfp_cpp_area *area;
7319af5a38SHeinrich Kuhn 
74*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu.", __func__,
7519af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
7619af5a38SHeinrich Kuhn 
7719af5a38SHeinrich Kuhn 	/* Reading the count param */
7819af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
7919af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
8019af5a38SHeinrich Kuhn 		return -EINVAL;
8119af5a38SHeinrich Kuhn 
8219af5a38SHeinrich Kuhn 	curlen = count;
8319af5a38SHeinrich Kuhn 
8419af5a38SHeinrich Kuhn 	/* Reading the offset param */
8519af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
8619af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
8719af5a38SHeinrich Kuhn 		return -EINVAL;
8819af5a38SHeinrich Kuhn 
8919af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
9019af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
9119af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
9219af5a38SHeinrich Kuhn 
93*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd.", __func__, count,
9419af5a38SHeinrich Kuhn 			offset);
95*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd.", __func__,
9619af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
9719af5a38SHeinrich Kuhn 
9819af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
9919af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
10019af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
10119af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
10219af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
10319af5a38SHeinrich Kuhn 	}
10419af5a38SHeinrich Kuhn 
10519af5a38SHeinrich Kuhn 	while (count > 0) {
106030b2b19SChaoyong He 		/* Configure a CPP PCIe2CPP BAR for mapping the CPP target */
10719af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
10819af5a38SHeinrich Kuhn 				nfp_offset, curlen);
109cbcbfd73SJames Hershaw 		if (area == NULL) {
110*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Area alloc fail.");
11119af5a38SHeinrich Kuhn 			return -EIO;
11219af5a38SHeinrich Kuhn 		}
11319af5a38SHeinrich Kuhn 
114030b2b19SChaoyong He 		/* Mapping the target */
11519af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
11619af5a38SHeinrich Kuhn 		if (err < 0) {
117*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Area acquire failed.");
11819af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
11919af5a38SHeinrich Kuhn 			return -EIO;
12019af5a38SHeinrich Kuhn 		}
12119af5a38SHeinrich Kuhn 
12219af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
12319af5a38SHeinrich Kuhn 			len = curlen - pos;
12419af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
12519af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
12619af5a38SHeinrich Kuhn 
127*b6de4353SZerun Fu 			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu.", __func__,
12819af5a38SHeinrich Kuhn 					len, count);
12919af5a38SHeinrich Kuhn 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
13019af5a38SHeinrich Kuhn 			if (err != (int)len) {
131*b6de4353SZerun Fu 				PMD_CPP_LOG(ERR, "Error when receiving, %d of %zu.",
13254fdb550SChaoyong He 						err, count);
13319af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
13419af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
13519af5a38SHeinrich Kuhn 				return -EIO;
13619af5a38SHeinrich Kuhn 			}
137b0c496abSChaoyong He 
13819af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
13919af5a38SHeinrich Kuhn 			if (err < 0) {
140*b6de4353SZerun Fu 				PMD_CPP_LOG(ERR, "The nfp_cpp_area_write error.");
14119af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
14219af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
14319af5a38SHeinrich Kuhn 				return -EIO;
14419af5a38SHeinrich Kuhn 			}
14519af5a38SHeinrich Kuhn 		}
14619af5a38SHeinrich Kuhn 
14719af5a38SHeinrich Kuhn 		nfp_offset += pos;
14819af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
14919af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
15019af5a38SHeinrich Kuhn 
15119af5a38SHeinrich Kuhn 		count -= pos;
15219af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
15319af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
15419af5a38SHeinrich Kuhn 	}
15519af5a38SHeinrich Kuhn 
15619af5a38SHeinrich Kuhn 	return 0;
15719af5a38SHeinrich Kuhn }
15819af5a38SHeinrich Kuhn 
15919af5a38SHeinrich Kuhn /*
16019af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
16119af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
16219af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
16319af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
16419af5a38SHeinrich Kuhn  */
16519af5a38SHeinrich Kuhn static int
166f4d24fe9SChaoyong He nfp_cpp_bridge_serve_read(int sockfd,
167f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
16819af5a38SHeinrich Kuhn {
16949952141SChaoyong He 	int err;
17049952141SChaoyong He 	off_t offset;
17149952141SChaoyong He 	uint32_t pos;
17249952141SChaoyong He 	uint32_t len;
17349952141SChaoyong He 	size_t count;
17449952141SChaoyong He 	size_t curlen;
17549952141SChaoyong He 	uint32_t cpp_id;
17649952141SChaoyong He 	off_t nfp_offset;
17719af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
17849952141SChaoyong He 	struct nfp_cpp_area *area;
17919af5a38SHeinrich Kuhn 
180*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu.", __func__,
18119af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
18219af5a38SHeinrich Kuhn 
18319af5a38SHeinrich Kuhn 	/* Reading the count param */
18419af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
18519af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
18619af5a38SHeinrich Kuhn 		return -EINVAL;
18719af5a38SHeinrich Kuhn 
18819af5a38SHeinrich Kuhn 	curlen = count;
18919af5a38SHeinrich Kuhn 
19019af5a38SHeinrich Kuhn 	/* Reading the offset param */
19119af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
19219af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
19319af5a38SHeinrich Kuhn 		return -EINVAL;
19419af5a38SHeinrich Kuhn 
19519af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
19619af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
19719af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
19819af5a38SHeinrich Kuhn 
199*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd.", __func__, count,
20019af5a38SHeinrich Kuhn 			offset);
201*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd.", __func__,
20219af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
20319af5a38SHeinrich Kuhn 
20419af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
20519af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
20619af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
20719af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
20819af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
20919af5a38SHeinrich Kuhn 	}
21019af5a38SHeinrich Kuhn 
21119af5a38SHeinrich Kuhn 	while (count > 0) {
21219af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
21319af5a38SHeinrich Kuhn 				nfp_offset, curlen);
214cbcbfd73SJames Hershaw 		if (area == NULL) {
215*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Area alloc failed.");
21619af5a38SHeinrich Kuhn 			return -EIO;
21719af5a38SHeinrich Kuhn 		}
21819af5a38SHeinrich Kuhn 
21919af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
22019af5a38SHeinrich Kuhn 		if (err < 0) {
221*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Area acquire failed.");
22219af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
22319af5a38SHeinrich Kuhn 			return -EIO;
22419af5a38SHeinrich Kuhn 		}
22519af5a38SHeinrich Kuhn 
22619af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
22719af5a38SHeinrich Kuhn 			len = curlen - pos;
22819af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
22919af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
23019af5a38SHeinrich Kuhn 
23119af5a38SHeinrich Kuhn 			err = nfp_cpp_area_read(area, pos, tmpbuf, len);
23219af5a38SHeinrich Kuhn 			if (err < 0) {
233*b6de4353SZerun Fu 				PMD_CPP_LOG(ERR, "The nfp_cpp_area_read error.");
23419af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
23519af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
23619af5a38SHeinrich Kuhn 				return -EIO;
23719af5a38SHeinrich Kuhn 			}
238*b6de4353SZerun Fu 			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu.", __func__,
23919af5a38SHeinrich Kuhn 					len, count);
24019af5a38SHeinrich Kuhn 
24119af5a38SHeinrich Kuhn 			err = send(sockfd, tmpbuf, len, 0);
24219af5a38SHeinrich Kuhn 			if (err != (int)len) {
243*b6de4353SZerun Fu 				PMD_CPP_LOG(ERR, "Error when sending: %d of %zu.",
24454fdb550SChaoyong He 						err, count);
24519af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
24619af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
24719af5a38SHeinrich Kuhn 				return -EIO;
24819af5a38SHeinrich Kuhn 			}
24919af5a38SHeinrich Kuhn 		}
25019af5a38SHeinrich Kuhn 
25119af5a38SHeinrich Kuhn 		nfp_offset += pos;
25219af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
25319af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
25419af5a38SHeinrich Kuhn 
25519af5a38SHeinrich Kuhn 		count -= pos;
25619af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
25719af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
25819af5a38SHeinrich Kuhn 	}
259b0c496abSChaoyong He 
26019af5a38SHeinrich Kuhn 	return 0;
26119af5a38SHeinrich Kuhn }
26219af5a38SHeinrich Kuhn 
26319af5a38SHeinrich Kuhn /*
26419af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
26519af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
26619af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
26719af5a38SHeinrich Kuhn  * does not require any CPP access at all.
26819af5a38SHeinrich Kuhn  */
26919af5a38SHeinrich Kuhn static int
270f4d24fe9SChaoyong He nfp_cpp_bridge_serve_ioctl(int sockfd,
271f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
27219af5a38SHeinrich Kuhn {
27319af5a38SHeinrich Kuhn 	int err;
27449952141SChaoyong He 	uint32_t cmd;
27549952141SChaoyong He 	uint32_t tmp;
27649952141SChaoyong He 	uint32_t ident_size;
27719af5a38SHeinrich Kuhn 
27819af5a38SHeinrich Kuhn 	/* Reading now the IOCTL command */
27919af5a38SHeinrich Kuhn 	err = recv(sockfd, &cmd, 4, 0);
28019af5a38SHeinrich Kuhn 	if (err != 4) {
281*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Read error from socket.");
28219af5a38SHeinrich Kuhn 		return -EIO;
28319af5a38SHeinrich Kuhn 	}
28419af5a38SHeinrich Kuhn 
28519af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
28619af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
287*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Unknown cmd %d.", cmd);
28819af5a38SHeinrich Kuhn 		return -EINVAL;
28919af5a38SHeinrich Kuhn 	}
29019af5a38SHeinrich Kuhn 
29119af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
29219af5a38SHeinrich Kuhn 	if (err != 4) {
293*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Read error from socket.");
29419af5a38SHeinrich Kuhn 		return -EIO;
29519af5a38SHeinrich Kuhn 	}
29619af5a38SHeinrich Kuhn 
29719af5a38SHeinrich Kuhn 	tmp = nfp_cpp_model(cpp);
29819af5a38SHeinrich Kuhn 
299*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: sending NFP model %08x.", __func__, tmp);
30019af5a38SHeinrich Kuhn 
30119af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
30219af5a38SHeinrich Kuhn 	if (err != 4) {
303*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Error writing to socket.");
30419af5a38SHeinrich Kuhn 		return -EIO;
30519af5a38SHeinrich Kuhn 	}
30619af5a38SHeinrich Kuhn 
307ff627b74SChaoyong He 	tmp = nfp_cpp_interface(cpp);
30819af5a38SHeinrich Kuhn 
309*b6de4353SZerun Fu 	PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x.", __func__, tmp);
31019af5a38SHeinrich Kuhn 
31119af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
31219af5a38SHeinrich Kuhn 	if (err != 4) {
313*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Error writing to socket.");
31419af5a38SHeinrich Kuhn 		return -EIO;
31519af5a38SHeinrich Kuhn 	}
31619af5a38SHeinrich Kuhn 
31719af5a38SHeinrich Kuhn 	return 0;
31819af5a38SHeinrich Kuhn }
31919af5a38SHeinrich Kuhn 
32019af5a38SHeinrich Kuhn /*
32119af5a38SHeinrich Kuhn  * This is the code to be executed by a service core. The CPP bridge interface
32219af5a38SHeinrich Kuhn  * is based on a unix socket and requests usually received by a kernel char
32319af5a38SHeinrich Kuhn  * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
32419af5a38SHeinrich Kuhn  * can be executed with a wrapper library and LD_LIBRARY being completely
32519af5a38SHeinrich Kuhn  * unaware of the CPP bridge performing the NFP kernel char driver for CPP
32619af5a38SHeinrich Kuhn  * accesses.
32719af5a38SHeinrich Kuhn  */
328b1880421SChaoyong He static int
32919af5a38SHeinrich Kuhn nfp_cpp_bridge_service_func(void *args)
33019af5a38SHeinrich Kuhn {
33149952141SChaoyong He 	int op;
33249952141SChaoyong He 	int ret;
33349952141SChaoyong He 	int sockfd;
33449952141SChaoyong He 	int datafd;
335bab0e6f4SChaoyong He 	struct nfp_cpp *cpp;
336600f6d2cSLong Wu 	const char *pci_name;
337600f6d2cSLong Wu 	char socket_handle[14];
33849952141SChaoyong He 	struct sockaddr address;
339bab0e6f4SChaoyong He 	struct nfp_pf_dev *pf_dev;
340a5b876a5SChaoyong He 	struct timeval timeout = {1, 0};
34119af5a38SHeinrich Kuhn 
342600f6d2cSLong Wu 	pf_dev = args;
343b0c496abSChaoyong He 
344600f6d2cSLong Wu 	pci_name = strchr(pf_dev->pci_dev->name, ':') + 1;
345600f6d2cSLong Wu 	snprintf(socket_handle, sizeof(socket_handle), "/tmp/%s", pci_name);
346600f6d2cSLong Wu 
347600f6d2cSLong Wu 	unlink(socket_handle);
34819af5a38SHeinrich Kuhn 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
34919af5a38SHeinrich Kuhn 	if (sockfd < 0) {
350*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Socket creation error. Service failed.");
35119af5a38SHeinrich Kuhn 		return -EIO;
35219af5a38SHeinrich Kuhn 	}
35319af5a38SHeinrich Kuhn 
354a5b876a5SChaoyong He 	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
355a5b876a5SChaoyong He 
35619af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
35719af5a38SHeinrich Kuhn 
35819af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
359600f6d2cSLong Wu 	strcpy(address.sa_data, socket_handle);
36019af5a38SHeinrich Kuhn 
36119af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
36219af5a38SHeinrich Kuhn 			sizeof(struct sockaddr));
36319af5a38SHeinrich Kuhn 	if (ret < 0) {
364*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Bind error (%d). Service failed.", errno);
36519af5a38SHeinrich Kuhn 		close(sockfd);
36619af5a38SHeinrich Kuhn 		return ret;
36719af5a38SHeinrich Kuhn 	}
36819af5a38SHeinrich Kuhn 
36919af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
37019af5a38SHeinrich Kuhn 	if (ret < 0) {
371*b6de4353SZerun Fu 		PMD_CPP_LOG(ERR, "Listen error(%d). Service failed.", errno);
37219af5a38SHeinrich Kuhn 		close(sockfd);
37319af5a38SHeinrich Kuhn 		return ret;
37419af5a38SHeinrich Kuhn 	}
37519af5a38SHeinrich Kuhn 
376bab0e6f4SChaoyong He 	cpp = pf_dev->cpp;
377600f6d2cSLong Wu 	while (rte_service_runstate_get(pf_dev->cpp_service_info.id) != 0) {
37819af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
37919af5a38SHeinrich Kuhn 		if (datafd < 0) {
380a5b876a5SChaoyong He 			if (errno == EAGAIN || errno == EWOULDBLOCK)
381a5b876a5SChaoyong He 				continue;
382a5b876a5SChaoyong He 
383*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Accept call error (%d).", errno);
384*b6de4353SZerun Fu 			PMD_CPP_LOG(ERR, "Service failed.");
38519af5a38SHeinrich Kuhn 			close(sockfd);
38619af5a38SHeinrich Kuhn 			return -EIO;
38719af5a38SHeinrich Kuhn 		}
38819af5a38SHeinrich Kuhn 
389e7978635SChaoyong He 		for (;;) {
39019af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
39119af5a38SHeinrich Kuhn 			if (ret <= 0) {
392*b6de4353SZerun Fu 				PMD_CPP_LOG(DEBUG, "%s: socket close.", __func__);
39319af5a38SHeinrich Kuhn 				break;
39419af5a38SHeinrich Kuhn 			}
39519af5a38SHeinrich Kuhn 
396*b6de4353SZerun Fu 			PMD_CPP_LOG(DEBUG, "%s: getting op %u.", __func__, op);
39719af5a38SHeinrich Kuhn 
39819af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
39919af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
40019af5a38SHeinrich Kuhn 
40119af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
40219af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
40319af5a38SHeinrich Kuhn 
40419af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
40519af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
40619af5a38SHeinrich Kuhn 
40719af5a38SHeinrich Kuhn 			if (op == 0)
40819af5a38SHeinrich Kuhn 				break;
40919af5a38SHeinrich Kuhn 		}
410b0c496abSChaoyong He 
41119af5a38SHeinrich Kuhn 		close(datafd);
41219af5a38SHeinrich Kuhn 	}
413b0c496abSChaoyong He 
41419af5a38SHeinrich Kuhn 	close(sockfd);
41519af5a38SHeinrich Kuhn 
41619af5a38SHeinrich Kuhn 	return 0;
41719af5a38SHeinrich Kuhn }
418