xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision 9465a5d5)
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  * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation.
619af5a38SHeinrich Kuhn  */
719af5a38SHeinrich Kuhn 
819af5a38SHeinrich Kuhn /*
919af5a38SHeinrich Kuhn  * vim:shiftwidth=8:noexpandtab
1019af5a38SHeinrich Kuhn  *
1119af5a38SHeinrich Kuhn  * @file dpdk/pmd/nfp_cpp_bridge.c
1219af5a38SHeinrich Kuhn  *
1319af5a38SHeinrich Kuhn  * Netronome vNIC DPDK Poll-Mode Driver: CPP Bridge
1419af5a38SHeinrich Kuhn  */
1519af5a38SHeinrich Kuhn 
1619af5a38SHeinrich Kuhn #include <rte_service_component.h>
1719af5a38SHeinrich Kuhn 
1819af5a38SHeinrich Kuhn #include "nfpcore/nfp_cpp.h"
1919af5a38SHeinrich Kuhn #include "nfpcore/nfp_mip.h"
2019af5a38SHeinrich Kuhn #include "nfpcore/nfp_nsp.h"
2119af5a38SHeinrich Kuhn 
228d7a59f1SHeinrich Kuhn #include "nfp_logs.h"
2319af5a38SHeinrich Kuhn #include "nfp_cpp_bridge.h"
2419af5a38SHeinrich Kuhn 
2519af5a38SHeinrich Kuhn #include <sys/ioctl.h>
2619af5a38SHeinrich Kuhn 
2719af5a38SHeinrich Kuhn /* Prototypes */
2819af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp);
2919af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp);
3019af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp);
3119af5a38SHeinrich Kuhn 
nfp_register_cpp_service(struct nfp_cpp * cpp)3219af5a38SHeinrich Kuhn void nfp_register_cpp_service(struct nfp_cpp *cpp)
3319af5a38SHeinrich Kuhn {
3419af5a38SHeinrich Kuhn 	uint32_t *cpp_service_id = NULL;
3519af5a38SHeinrich Kuhn 	struct rte_service_spec service;
3619af5a38SHeinrich Kuhn 
3719af5a38SHeinrich Kuhn 	memset(&service, 0, sizeof(struct rte_service_spec));
3819af5a38SHeinrich Kuhn 	snprintf(service.name, sizeof(service.name), "nfp_cpp_service");
3919af5a38SHeinrich Kuhn 	service.callback = nfp_cpp_bridge_service_func;
4019af5a38SHeinrich Kuhn 	service.callback_userdata = (void *)cpp;
4119af5a38SHeinrich Kuhn 
4219af5a38SHeinrich Kuhn 	if (rte_service_component_register(&service,
4319af5a38SHeinrich Kuhn 					   cpp_service_id))
4419af5a38SHeinrich Kuhn 		RTE_LOG(WARNING, PMD, "NFP CPP bridge service register() failed");
4519af5a38SHeinrich Kuhn 	else
4619af5a38SHeinrich Kuhn 		RTE_LOG(DEBUG, PMD, "NFP CPP bridge service registered");
4719af5a38SHeinrich Kuhn }
4819af5a38SHeinrich Kuhn 
4919af5a38SHeinrich Kuhn /*
5019af5a38SHeinrich Kuhn  * Serving a write request to NFP from host programs. The request
5119af5a38SHeinrich Kuhn  * sends the write size and the CPP target. The bridge makes use
5219af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup.
5319af5a38SHeinrich Kuhn  */
5419af5a38SHeinrich Kuhn static int
nfp_cpp_bridge_serve_write(int sockfd,struct nfp_cpp * cpp)5519af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp)
5619af5a38SHeinrich Kuhn {
5719af5a38SHeinrich Kuhn 	struct nfp_cpp_area *area;
5819af5a38SHeinrich Kuhn 	off_t offset, nfp_offset;
5919af5a38SHeinrich Kuhn 	uint32_t cpp_id, pos, len;
6019af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
61*9465a5d5SConor Walsh 	size_t count, curlen;
6219af5a38SHeinrich Kuhn 	int err = 0;
6319af5a38SHeinrich Kuhn 
6419af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
6519af5a38SHeinrich Kuhn 		sizeof(off_t), sizeof(size_t));
6619af5a38SHeinrich Kuhn 
6719af5a38SHeinrich Kuhn 	/* Reading the count param */
6819af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
6919af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
7019af5a38SHeinrich Kuhn 		return -EINVAL;
7119af5a38SHeinrich Kuhn 
7219af5a38SHeinrich Kuhn 	curlen = count;
7319af5a38SHeinrich Kuhn 
7419af5a38SHeinrich Kuhn 	/* Reading the offset param */
7519af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
7619af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
7719af5a38SHeinrich Kuhn 		return -EINVAL;
7819af5a38SHeinrich Kuhn 
7919af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
8019af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
8119af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
8219af5a38SHeinrich Kuhn 
8319af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
8419af5a38SHeinrich Kuhn 		offset);
8519af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
8619af5a38SHeinrich Kuhn 		cpp_id, nfp_offset);
8719af5a38SHeinrich Kuhn 
8819af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
8919af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
9019af5a38SHeinrich Kuhn 	    (nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
9119af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
9219af5a38SHeinrich Kuhn 			(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
9319af5a38SHeinrich Kuhn 	}
9419af5a38SHeinrich Kuhn 
9519af5a38SHeinrich Kuhn 	while (count > 0) {
9619af5a38SHeinrich Kuhn 		/* configure a CPP PCIe2CPP BAR for mapping the CPP target */
9719af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
9819af5a38SHeinrich Kuhn 						    nfp_offset, curlen);
9919af5a38SHeinrich Kuhn 		if (!area) {
10019af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: area alloc fail\n", __func__);
10119af5a38SHeinrich Kuhn 			return -EIO;
10219af5a38SHeinrich Kuhn 		}
10319af5a38SHeinrich Kuhn 
10419af5a38SHeinrich Kuhn 		/* mapping the target */
10519af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
10619af5a38SHeinrich Kuhn 		if (err < 0) {
10719af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "area acquire failed\n");
10819af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
10919af5a38SHeinrich Kuhn 			return -EIO;
11019af5a38SHeinrich Kuhn 		}
11119af5a38SHeinrich Kuhn 
11219af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
11319af5a38SHeinrich Kuhn 			len = curlen - pos;
11419af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
11519af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
11619af5a38SHeinrich Kuhn 
11719af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu\n", __func__,
11819af5a38SHeinrich Kuhn 					   len, count);
11919af5a38SHeinrich Kuhn 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
12019af5a38SHeinrich Kuhn 			if (err != (int)len) {
12119af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD,
12219af5a38SHeinrich Kuhn 					"%s: error when receiving, %d of %zu\n",
12319af5a38SHeinrich Kuhn 					__func__, err, count);
12419af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
12519af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
12619af5a38SHeinrich Kuhn 				return -EIO;
12719af5a38SHeinrich Kuhn 			}
12819af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
12919af5a38SHeinrich Kuhn 			if (err < 0) {
13019af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD, "nfp_cpp_area_write error\n");
13119af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
13219af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
13319af5a38SHeinrich Kuhn 				return -EIO;
13419af5a38SHeinrich Kuhn 			}
13519af5a38SHeinrich Kuhn 		}
13619af5a38SHeinrich Kuhn 
13719af5a38SHeinrich Kuhn 		nfp_offset += pos;
13819af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
13919af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
14019af5a38SHeinrich Kuhn 
14119af5a38SHeinrich Kuhn 		count -= pos;
14219af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
14319af5a38SHeinrich Kuhn 			 NFP_CPP_MEMIO_BOUNDARY : count;
14419af5a38SHeinrich Kuhn 	}
14519af5a38SHeinrich Kuhn 
14619af5a38SHeinrich Kuhn 	return 0;
14719af5a38SHeinrich Kuhn }
14819af5a38SHeinrich Kuhn 
14919af5a38SHeinrich Kuhn /*
15019af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
15119af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
15219af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
15319af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
15419af5a38SHeinrich Kuhn  */
15519af5a38SHeinrich Kuhn static int
nfp_cpp_bridge_serve_read(int sockfd,struct nfp_cpp * cpp)15619af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp)
15719af5a38SHeinrich Kuhn {
15819af5a38SHeinrich Kuhn 	struct nfp_cpp_area *area;
15919af5a38SHeinrich Kuhn 	off_t offset, nfp_offset;
16019af5a38SHeinrich Kuhn 	uint32_t cpp_id, pos, len;
16119af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
162*9465a5d5SConor Walsh 	size_t count, curlen;
16319af5a38SHeinrich Kuhn 	int err = 0;
16419af5a38SHeinrich Kuhn 
16519af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
16619af5a38SHeinrich Kuhn 		sizeof(off_t), sizeof(size_t));
16719af5a38SHeinrich Kuhn 
16819af5a38SHeinrich Kuhn 	/* Reading the count param */
16919af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
17019af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
17119af5a38SHeinrich Kuhn 		return -EINVAL;
17219af5a38SHeinrich Kuhn 
17319af5a38SHeinrich Kuhn 	curlen = count;
17419af5a38SHeinrich Kuhn 
17519af5a38SHeinrich Kuhn 	/* Reading the offset param */
17619af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
17719af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
17819af5a38SHeinrich Kuhn 		return -EINVAL;
17919af5a38SHeinrich Kuhn 
18019af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
18119af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
18219af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
18319af5a38SHeinrich Kuhn 
18419af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
18519af5a38SHeinrich Kuhn 			   offset);
18619af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
18719af5a38SHeinrich Kuhn 			   cpp_id, nfp_offset);
18819af5a38SHeinrich Kuhn 
18919af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
19019af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
19119af5a38SHeinrich Kuhn 	    (nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
19219af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
19319af5a38SHeinrich Kuhn 			(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
19419af5a38SHeinrich Kuhn 	}
19519af5a38SHeinrich Kuhn 
19619af5a38SHeinrich Kuhn 	while (count > 0) {
19719af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
19819af5a38SHeinrich Kuhn 						    nfp_offset, curlen);
19919af5a38SHeinrich Kuhn 		if (!area) {
20019af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: area alloc failed\n", __func__);
20119af5a38SHeinrich Kuhn 			return -EIO;
20219af5a38SHeinrich Kuhn 		}
20319af5a38SHeinrich Kuhn 
20419af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
20519af5a38SHeinrich Kuhn 		if (err < 0) {
20619af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "area acquire failed\n");
20719af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
20819af5a38SHeinrich Kuhn 			return -EIO;
20919af5a38SHeinrich Kuhn 		}
21019af5a38SHeinrich Kuhn 
21119af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
21219af5a38SHeinrich Kuhn 			len = curlen - pos;
21319af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
21419af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
21519af5a38SHeinrich Kuhn 
21619af5a38SHeinrich Kuhn 			err = nfp_cpp_area_read(area, pos, tmpbuf, len);
21719af5a38SHeinrich Kuhn 			if (err < 0) {
21819af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD, "nfp_cpp_area_read error\n");
21919af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
22019af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
22119af5a38SHeinrich Kuhn 				return -EIO;
22219af5a38SHeinrich Kuhn 			}
22319af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu\n", __func__,
22419af5a38SHeinrich Kuhn 					   len, count);
22519af5a38SHeinrich Kuhn 
22619af5a38SHeinrich Kuhn 			err = send(sockfd, tmpbuf, len, 0);
22719af5a38SHeinrich Kuhn 			if (err != (int)len) {
22819af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD,
22919af5a38SHeinrich Kuhn 					"%s: error when sending: %d of %zu\n",
23019af5a38SHeinrich Kuhn 					__func__, err, count);
23119af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
23219af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
23319af5a38SHeinrich Kuhn 				return -EIO;
23419af5a38SHeinrich Kuhn 			}
23519af5a38SHeinrich Kuhn 		}
23619af5a38SHeinrich Kuhn 
23719af5a38SHeinrich Kuhn 		nfp_offset += pos;
23819af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
23919af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
24019af5a38SHeinrich Kuhn 
24119af5a38SHeinrich Kuhn 		count -= pos;
24219af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
24319af5a38SHeinrich Kuhn 			NFP_CPP_MEMIO_BOUNDARY : count;
24419af5a38SHeinrich Kuhn 	}
24519af5a38SHeinrich Kuhn 	return 0;
24619af5a38SHeinrich Kuhn }
24719af5a38SHeinrich Kuhn 
24819af5a38SHeinrich Kuhn /*
24919af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
25019af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
25119af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
25219af5a38SHeinrich Kuhn  * does not require any CPP access at all.
25319af5a38SHeinrich Kuhn  */
25419af5a38SHeinrich Kuhn static int
nfp_cpp_bridge_serve_ioctl(int sockfd,struct nfp_cpp * cpp)25519af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp)
25619af5a38SHeinrich Kuhn {
25719af5a38SHeinrich Kuhn 	uint32_t cmd, ident_size, tmp;
25819af5a38SHeinrich Kuhn 	int err;
25919af5a38SHeinrich Kuhn 
26019af5a38SHeinrich Kuhn 	/* Reading now the IOCTL command */
26119af5a38SHeinrich Kuhn 	err = recv(sockfd, &cmd, 4, 0);
26219af5a38SHeinrich Kuhn 	if (err != 4) {
26319af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: read error from socket\n", __func__);
26419af5a38SHeinrich Kuhn 		return -EIO;
26519af5a38SHeinrich Kuhn 	}
26619af5a38SHeinrich Kuhn 
26719af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
26819af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
26919af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: unknown cmd %d\n", __func__, cmd);
27019af5a38SHeinrich Kuhn 		return -EINVAL;
27119af5a38SHeinrich Kuhn 	}
27219af5a38SHeinrich Kuhn 
27319af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
27419af5a38SHeinrich Kuhn 	if (err != 4) {
27519af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: read error from socket\n", __func__);
27619af5a38SHeinrich Kuhn 		return -EIO;
27719af5a38SHeinrich Kuhn 	}
27819af5a38SHeinrich Kuhn 
27919af5a38SHeinrich Kuhn 	tmp = nfp_cpp_model(cpp);
28019af5a38SHeinrich Kuhn 
28119af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: sending NFP model %08x\n", __func__, tmp);
28219af5a38SHeinrich Kuhn 
28319af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
28419af5a38SHeinrich Kuhn 	if (err != 4) {
28519af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: error writing to socket\n", __func__);
28619af5a38SHeinrich Kuhn 		return -EIO;
28719af5a38SHeinrich Kuhn 	}
28819af5a38SHeinrich Kuhn 
28919af5a38SHeinrich Kuhn 	tmp = cpp->interface;
29019af5a38SHeinrich Kuhn 
29119af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x\n", __func__, tmp);
29219af5a38SHeinrich Kuhn 
29319af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
29419af5a38SHeinrich Kuhn 	if (err != 4) {
29519af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: error writing to socket\n", __func__);
29619af5a38SHeinrich Kuhn 		return -EIO;
29719af5a38SHeinrich Kuhn 	}
29819af5a38SHeinrich Kuhn 
29919af5a38SHeinrich Kuhn 	return 0;
30019af5a38SHeinrich Kuhn }
30119af5a38SHeinrich Kuhn 
30219af5a38SHeinrich Kuhn /*
30319af5a38SHeinrich Kuhn  * This is the code to be executed by a service core. The CPP bridge interface
30419af5a38SHeinrich Kuhn  * is based on a unix socket and requests usually received by a kernel char
30519af5a38SHeinrich Kuhn  * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
30619af5a38SHeinrich Kuhn  * can be executed with a wrapper library and LD_LIBRARY being completely
30719af5a38SHeinrich Kuhn  * unaware of the CPP bridge performing the NFP kernel char driver for CPP
30819af5a38SHeinrich Kuhn  * accesses.
30919af5a38SHeinrich Kuhn  */
31019af5a38SHeinrich Kuhn int32_t
nfp_cpp_bridge_service_func(void * args)31119af5a38SHeinrich Kuhn nfp_cpp_bridge_service_func(void *args)
31219af5a38SHeinrich Kuhn {
31319af5a38SHeinrich Kuhn 	struct sockaddr address;
31419af5a38SHeinrich Kuhn 	struct nfp_cpp *cpp = args;
31519af5a38SHeinrich Kuhn 	int sockfd, datafd, op, ret;
31619af5a38SHeinrich Kuhn 
31719af5a38SHeinrich Kuhn 	unlink("/tmp/nfp_cpp");
31819af5a38SHeinrich Kuhn 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
31919af5a38SHeinrich Kuhn 	if (sockfd < 0) {
32019af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: socket creation error. Service failed\n",
32119af5a38SHeinrich Kuhn 			__func__);
32219af5a38SHeinrich Kuhn 		return -EIO;
32319af5a38SHeinrich Kuhn 	}
32419af5a38SHeinrich Kuhn 
32519af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
32619af5a38SHeinrich Kuhn 
32719af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
32819af5a38SHeinrich Kuhn 	strcpy(address.sa_data, "/tmp/nfp_cpp");
32919af5a38SHeinrich Kuhn 
33019af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
33119af5a38SHeinrich Kuhn 		   sizeof(struct sockaddr));
33219af5a38SHeinrich Kuhn 	if (ret < 0) {
33319af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: bind error (%d). Service failed\n",
33419af5a38SHeinrich Kuhn 				  __func__, errno);
33519af5a38SHeinrich Kuhn 		close(sockfd);
33619af5a38SHeinrich Kuhn 		return ret;
33719af5a38SHeinrich Kuhn 	}
33819af5a38SHeinrich Kuhn 
33919af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
34019af5a38SHeinrich Kuhn 	if (ret < 0) {
34119af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: listen error(%d). Service failed\n",
34219af5a38SHeinrich Kuhn 				  __func__, errno);
34319af5a38SHeinrich Kuhn 		close(sockfd);
34419af5a38SHeinrich Kuhn 		return ret;
34519af5a38SHeinrich Kuhn 	}
34619af5a38SHeinrich Kuhn 
34719af5a38SHeinrich Kuhn 	for (;;) {
34819af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
34919af5a38SHeinrich Kuhn 		if (datafd < 0) {
35019af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: accept call error (%d)\n",
35119af5a38SHeinrich Kuhn 					  __func__, errno);
35219af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: service failed\n", __func__);
35319af5a38SHeinrich Kuhn 			close(sockfd);
35419af5a38SHeinrich Kuhn 			return -EIO;
35519af5a38SHeinrich Kuhn 		}
35619af5a38SHeinrich Kuhn 
35719af5a38SHeinrich Kuhn 		while (1) {
35819af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
35919af5a38SHeinrich Kuhn 			if (ret <= 0) {
36019af5a38SHeinrich Kuhn 				PMD_CPP_LOG(DEBUG, "%s: socket close\n",
36119af5a38SHeinrich Kuhn 						   __func__);
36219af5a38SHeinrich Kuhn 				break;
36319af5a38SHeinrich Kuhn 			}
36419af5a38SHeinrich Kuhn 
36519af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: getting op %u\n", __func__, op);
36619af5a38SHeinrich Kuhn 
36719af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
36819af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
36919af5a38SHeinrich Kuhn 
37019af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
37119af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
37219af5a38SHeinrich Kuhn 
37319af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
37419af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
37519af5a38SHeinrich Kuhn 
37619af5a38SHeinrich Kuhn 			if (op == 0)
37719af5a38SHeinrich Kuhn 				break;
37819af5a38SHeinrich Kuhn 		}
37919af5a38SHeinrich Kuhn 		close(datafd);
38019af5a38SHeinrich Kuhn 	}
38119af5a38SHeinrich Kuhn 	close(sockfd);
38219af5a38SHeinrich Kuhn 
38319af5a38SHeinrich Kuhn 	return 0;
38419af5a38SHeinrich Kuhn }
38519af5a38SHeinrich Kuhn /*
38619af5a38SHeinrich Kuhn  * Local variables:
38719af5a38SHeinrich Kuhn  * c-file-style: "Linux"
38819af5a38SHeinrich Kuhn  * indent-tabs-mode: t
38919af5a38SHeinrich Kuhn  * End:
39019af5a38SHeinrich Kuhn  */
391