xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision cbcbfd731e0d8076f873ce4e86aa6738199d42eb)
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);
31b1880421SChaoyong He static int nfp_cpp_bridge_service_func(void *args);
3219af5a38SHeinrich Kuhn 
33b1880421SChaoyong He int
34b1880421SChaoyong He nfp_map_service(uint32_t service_id)
3519af5a38SHeinrich Kuhn {
36b1880421SChaoyong He 	int32_t ret;
37b1880421SChaoyong He 	uint32_t slcore = 0;
38b1880421SChaoyong He 	int32_t slcore_count;
39b1880421SChaoyong He 	uint8_t service_count;
40b1880421SChaoyong He 	const char *service_name;
41b1880421SChaoyong He 	uint32_t slcore_array[RTE_MAX_LCORE];
42b1880421SChaoyong He 	uint8_t min_service_count = UINT8_MAX;
4319af5a38SHeinrich Kuhn 
44b1880421SChaoyong He 	slcore_count = rte_service_lcore_list(slcore_array, RTE_MAX_LCORE);
45b1880421SChaoyong He 	if (slcore_count <= 0) {
46b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "No service cores found");
47b1880421SChaoyong He 		return -ENOENT;
48b1880421SChaoyong He 	}
4919af5a38SHeinrich Kuhn 
50b1880421SChaoyong He 	/*
51b1880421SChaoyong He 	 * Find a service core with the least number of services already
52b1880421SChaoyong He 	 * registered to it
53b1880421SChaoyong He 	 */
54b1880421SChaoyong He 	while (slcore_count--) {
55b1880421SChaoyong He 		service_count = rte_service_lcore_count_services(slcore_array[slcore_count]);
56b1880421SChaoyong He 		if (service_count < min_service_count) {
57b1880421SChaoyong He 			slcore = slcore_array[slcore_count];
58b1880421SChaoyong He 			min_service_count = service_count;
59b1880421SChaoyong He 		}
60b1880421SChaoyong He 	}
61b1880421SChaoyong He 
62b1880421SChaoyong He 	service_name = rte_service_get_name(service_id);
63b1880421SChaoyong He 	PMD_INIT_LOG(INFO, "Mapping service %s to core %u", service_name, slcore);
64b1880421SChaoyong He 
65b1880421SChaoyong He 	ret = rte_service_map_lcore_set(service_id, slcore, 1);
66b1880421SChaoyong He 	if (ret != 0) {
67b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "Could not map flower service");
68b1880421SChaoyong He 		return -ENOENT;
69b1880421SChaoyong He 	}
70b1880421SChaoyong He 
71b1880421SChaoyong He 	rte_service_runstate_set(service_id, 1);
72b1880421SChaoyong He 	rte_service_component_runstate_set(service_id, 1);
73b1880421SChaoyong He 	rte_service_lcore_start(slcore);
74b1880421SChaoyong He 	if (rte_service_may_be_active(slcore))
75b1880421SChaoyong He 		PMD_INIT_LOG(INFO, "The service %s is running", service_name);
7619af5a38SHeinrich Kuhn 	else
77b1880421SChaoyong He 		PMD_INIT_LOG(ERR, "The service %s is not running", service_name);
78b1880421SChaoyong He 
79b1880421SChaoyong He 	return 0;
80b1880421SChaoyong He }
81b1880421SChaoyong He 
82b1880421SChaoyong He int
83bab0e6f4SChaoyong He nfp_enable_cpp_service(struct nfp_pf_dev *pf_dev)
84b1880421SChaoyong He {
85b1880421SChaoyong He 	int ret;
86b1880421SChaoyong He 	uint32_t service_id = 0;
87b1880421SChaoyong He 	struct rte_service_spec cpp_service = {
88b1880421SChaoyong He 		.name         = "nfp_cpp_service",
89b1880421SChaoyong He 		.callback     = nfp_cpp_bridge_service_func,
90b1880421SChaoyong He 	};
91b1880421SChaoyong He 
92bab0e6f4SChaoyong He 	cpp_service.callback_userdata = (void *)pf_dev;
93b1880421SChaoyong He 
94b1880421SChaoyong He 	/* Register the cpp service */
95b1880421SChaoyong He 	ret = rte_service_component_register(&cpp_service, &service_id);
96b1880421SChaoyong He 	if (ret != 0) {
97b1880421SChaoyong He 		PMD_INIT_LOG(WARNING, "Could not register nfp cpp service");
98b1880421SChaoyong He 		return -EINVAL;
99b1880421SChaoyong He 	}
100b1880421SChaoyong He 
101bab0e6f4SChaoyong He 	pf_dev->cpp_bridge_id = service_id;
102b1880421SChaoyong He 	PMD_INIT_LOG(INFO, "NFP cpp service registered");
103b1880421SChaoyong He 
104b1880421SChaoyong He 	/* Map it to available service core*/
105b1880421SChaoyong He 	ret = nfp_map_service(service_id);
106b1880421SChaoyong He 	if (ret != 0) {
107b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "Could not map nfp cpp service");
108b1880421SChaoyong He 		return -EINVAL;
109b1880421SChaoyong He 	}
110b1880421SChaoyong He 
111b1880421SChaoyong He 	return 0;
11219af5a38SHeinrich Kuhn }
11319af5a38SHeinrich Kuhn 
11419af5a38SHeinrich Kuhn /*
11519af5a38SHeinrich Kuhn  * Serving a write request to NFP from host programs. The request
11619af5a38SHeinrich Kuhn  * sends the write size and the CPP target. The bridge makes use
11719af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup.
11819af5a38SHeinrich Kuhn  */
11919af5a38SHeinrich Kuhn static int
12019af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp)
12119af5a38SHeinrich Kuhn {
12219af5a38SHeinrich Kuhn 	struct nfp_cpp_area *area;
12319af5a38SHeinrich Kuhn 	off_t offset, nfp_offset;
12419af5a38SHeinrich Kuhn 	uint32_t cpp_id, pos, len;
12519af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
1269465a5d5SConor Walsh 	size_t count, curlen;
12719af5a38SHeinrich Kuhn 	int err = 0;
12819af5a38SHeinrich Kuhn 
12919af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
13019af5a38SHeinrich Kuhn 		sizeof(off_t), sizeof(size_t));
13119af5a38SHeinrich Kuhn 
13219af5a38SHeinrich Kuhn 	/* Reading the count param */
13319af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
13419af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
13519af5a38SHeinrich Kuhn 		return -EINVAL;
13619af5a38SHeinrich Kuhn 
13719af5a38SHeinrich Kuhn 	curlen = count;
13819af5a38SHeinrich Kuhn 
13919af5a38SHeinrich Kuhn 	/* Reading the offset param */
14019af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
14119af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
14219af5a38SHeinrich Kuhn 		return -EINVAL;
14319af5a38SHeinrich Kuhn 
14419af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
14519af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
14619af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
14719af5a38SHeinrich Kuhn 
14819af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
14919af5a38SHeinrich Kuhn 		offset);
15019af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
15119af5a38SHeinrich Kuhn 		cpp_id, nfp_offset);
15219af5a38SHeinrich Kuhn 
15319af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
15419af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
15519af5a38SHeinrich Kuhn 	    (nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
15619af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
15719af5a38SHeinrich Kuhn 			(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
15819af5a38SHeinrich Kuhn 	}
15919af5a38SHeinrich Kuhn 
16019af5a38SHeinrich Kuhn 	while (count > 0) {
16119af5a38SHeinrich Kuhn 		/* configure a CPP PCIe2CPP BAR for mapping the CPP target */
16219af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
16319af5a38SHeinrich Kuhn 						    nfp_offset, curlen);
164*cbcbfd73SJames Hershaw 		if (area == NULL) {
16519af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: area alloc fail\n", __func__);
16619af5a38SHeinrich Kuhn 			return -EIO;
16719af5a38SHeinrich Kuhn 		}
16819af5a38SHeinrich Kuhn 
16919af5a38SHeinrich Kuhn 		/* mapping the target */
17019af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
17119af5a38SHeinrich Kuhn 		if (err < 0) {
17219af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "area acquire failed\n");
17319af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
17419af5a38SHeinrich Kuhn 			return -EIO;
17519af5a38SHeinrich Kuhn 		}
17619af5a38SHeinrich Kuhn 
17719af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
17819af5a38SHeinrich Kuhn 			len = curlen - pos;
17919af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
18019af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
18119af5a38SHeinrich Kuhn 
18219af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu\n", __func__,
18319af5a38SHeinrich Kuhn 					   len, count);
18419af5a38SHeinrich Kuhn 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
18519af5a38SHeinrich Kuhn 			if (err != (int)len) {
18619af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD,
18719af5a38SHeinrich Kuhn 					"%s: error when receiving, %d of %zu\n",
18819af5a38SHeinrich Kuhn 					__func__, err, count);
18919af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
19019af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
19119af5a38SHeinrich Kuhn 				return -EIO;
19219af5a38SHeinrich Kuhn 			}
19319af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
19419af5a38SHeinrich Kuhn 			if (err < 0) {
19519af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD, "nfp_cpp_area_write error\n");
19619af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
19719af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
19819af5a38SHeinrich Kuhn 				return -EIO;
19919af5a38SHeinrich Kuhn 			}
20019af5a38SHeinrich Kuhn 		}
20119af5a38SHeinrich Kuhn 
20219af5a38SHeinrich Kuhn 		nfp_offset += pos;
20319af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
20419af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
20519af5a38SHeinrich Kuhn 
20619af5a38SHeinrich Kuhn 		count -= pos;
20719af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
20819af5a38SHeinrich Kuhn 			 NFP_CPP_MEMIO_BOUNDARY : count;
20919af5a38SHeinrich Kuhn 	}
21019af5a38SHeinrich Kuhn 
21119af5a38SHeinrich Kuhn 	return 0;
21219af5a38SHeinrich Kuhn }
21319af5a38SHeinrich Kuhn 
21419af5a38SHeinrich Kuhn /*
21519af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
21619af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
21719af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
21819af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
21919af5a38SHeinrich Kuhn  */
22019af5a38SHeinrich Kuhn static int
22119af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp)
22219af5a38SHeinrich Kuhn {
22319af5a38SHeinrich Kuhn 	struct nfp_cpp_area *area;
22419af5a38SHeinrich Kuhn 	off_t offset, nfp_offset;
22519af5a38SHeinrich Kuhn 	uint32_t cpp_id, pos, len;
22619af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
2279465a5d5SConor Walsh 	size_t count, curlen;
22819af5a38SHeinrich Kuhn 	int err = 0;
22919af5a38SHeinrich Kuhn 
23019af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu\n", __func__,
23119af5a38SHeinrich Kuhn 		sizeof(off_t), sizeof(size_t));
23219af5a38SHeinrich Kuhn 
23319af5a38SHeinrich Kuhn 	/* Reading the count param */
23419af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
23519af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
23619af5a38SHeinrich Kuhn 		return -EINVAL;
23719af5a38SHeinrich Kuhn 
23819af5a38SHeinrich Kuhn 	curlen = count;
23919af5a38SHeinrich Kuhn 
24019af5a38SHeinrich Kuhn 	/* Reading the offset param */
24119af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
24219af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
24319af5a38SHeinrich Kuhn 		return -EINVAL;
24419af5a38SHeinrich Kuhn 
24519af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
24619af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
24719af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
24819af5a38SHeinrich Kuhn 
24919af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd\n", __func__, count,
25019af5a38SHeinrich Kuhn 			   offset);
25119af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd\n", __func__,
25219af5a38SHeinrich Kuhn 			   cpp_id, nfp_offset);
25319af5a38SHeinrich Kuhn 
25419af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
25519af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
25619af5a38SHeinrich Kuhn 	    (nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
25719af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
25819af5a38SHeinrich Kuhn 			(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
25919af5a38SHeinrich Kuhn 	}
26019af5a38SHeinrich Kuhn 
26119af5a38SHeinrich Kuhn 	while (count > 0) {
26219af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
26319af5a38SHeinrich Kuhn 						    nfp_offset, curlen);
264*cbcbfd73SJames Hershaw 		if (area == NULL) {
26519af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: area alloc failed\n", __func__);
26619af5a38SHeinrich Kuhn 			return -EIO;
26719af5a38SHeinrich Kuhn 		}
26819af5a38SHeinrich Kuhn 
26919af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
27019af5a38SHeinrich Kuhn 		if (err < 0) {
27119af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "area acquire failed\n");
27219af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
27319af5a38SHeinrich Kuhn 			return -EIO;
27419af5a38SHeinrich Kuhn 		}
27519af5a38SHeinrich Kuhn 
27619af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
27719af5a38SHeinrich Kuhn 			len = curlen - pos;
27819af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
27919af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
28019af5a38SHeinrich Kuhn 
28119af5a38SHeinrich Kuhn 			err = nfp_cpp_area_read(area, pos, tmpbuf, len);
28219af5a38SHeinrich Kuhn 			if (err < 0) {
28319af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD, "nfp_cpp_area_read error\n");
28419af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
28519af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
28619af5a38SHeinrich Kuhn 				return -EIO;
28719af5a38SHeinrich Kuhn 			}
28819af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu\n", __func__,
28919af5a38SHeinrich Kuhn 					   len, count);
29019af5a38SHeinrich Kuhn 
29119af5a38SHeinrich Kuhn 			err = send(sockfd, tmpbuf, len, 0);
29219af5a38SHeinrich Kuhn 			if (err != (int)len) {
29319af5a38SHeinrich Kuhn 				RTE_LOG(ERR, PMD,
29419af5a38SHeinrich Kuhn 					"%s: error when sending: %d of %zu\n",
29519af5a38SHeinrich Kuhn 					__func__, err, count);
29619af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
29719af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
29819af5a38SHeinrich Kuhn 				return -EIO;
29919af5a38SHeinrich Kuhn 			}
30019af5a38SHeinrich Kuhn 		}
30119af5a38SHeinrich Kuhn 
30219af5a38SHeinrich Kuhn 		nfp_offset += pos;
30319af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
30419af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
30519af5a38SHeinrich Kuhn 
30619af5a38SHeinrich Kuhn 		count -= pos;
30719af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
30819af5a38SHeinrich Kuhn 			NFP_CPP_MEMIO_BOUNDARY : count;
30919af5a38SHeinrich Kuhn 	}
31019af5a38SHeinrich Kuhn 	return 0;
31119af5a38SHeinrich Kuhn }
31219af5a38SHeinrich Kuhn 
31319af5a38SHeinrich Kuhn /*
31419af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
31519af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
31619af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
31719af5a38SHeinrich Kuhn  * does not require any CPP access at all.
31819af5a38SHeinrich Kuhn  */
31919af5a38SHeinrich Kuhn static int
32019af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp)
32119af5a38SHeinrich Kuhn {
32219af5a38SHeinrich Kuhn 	uint32_t cmd, ident_size, tmp;
32319af5a38SHeinrich Kuhn 	int err;
32419af5a38SHeinrich Kuhn 
32519af5a38SHeinrich Kuhn 	/* Reading now the IOCTL command */
32619af5a38SHeinrich Kuhn 	err = recv(sockfd, &cmd, 4, 0);
32719af5a38SHeinrich Kuhn 	if (err != 4) {
32819af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: read error from socket\n", __func__);
32919af5a38SHeinrich Kuhn 		return -EIO;
33019af5a38SHeinrich Kuhn 	}
33119af5a38SHeinrich Kuhn 
33219af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
33319af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
33419af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: unknown cmd %d\n", __func__, cmd);
33519af5a38SHeinrich Kuhn 		return -EINVAL;
33619af5a38SHeinrich Kuhn 	}
33719af5a38SHeinrich Kuhn 
33819af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
33919af5a38SHeinrich Kuhn 	if (err != 4) {
34019af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: read error from socket\n", __func__);
34119af5a38SHeinrich Kuhn 		return -EIO;
34219af5a38SHeinrich Kuhn 	}
34319af5a38SHeinrich Kuhn 
34419af5a38SHeinrich Kuhn 	tmp = nfp_cpp_model(cpp);
34519af5a38SHeinrich Kuhn 
34619af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: sending NFP model %08x\n", __func__, tmp);
34719af5a38SHeinrich Kuhn 
34819af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
34919af5a38SHeinrich Kuhn 	if (err != 4) {
35019af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: error writing to socket\n", __func__);
35119af5a38SHeinrich Kuhn 		return -EIO;
35219af5a38SHeinrich Kuhn 	}
35319af5a38SHeinrich Kuhn 
35419af5a38SHeinrich Kuhn 	tmp = cpp->interface;
35519af5a38SHeinrich Kuhn 
35619af5a38SHeinrich Kuhn 	PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x\n", __func__, tmp);
35719af5a38SHeinrich Kuhn 
35819af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
35919af5a38SHeinrich Kuhn 	if (err != 4) {
36019af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: error writing to socket\n", __func__);
36119af5a38SHeinrich Kuhn 		return -EIO;
36219af5a38SHeinrich Kuhn 	}
36319af5a38SHeinrich Kuhn 
36419af5a38SHeinrich Kuhn 	return 0;
36519af5a38SHeinrich Kuhn }
36619af5a38SHeinrich Kuhn 
36719af5a38SHeinrich Kuhn /*
36819af5a38SHeinrich Kuhn  * This is the code to be executed by a service core. The CPP bridge interface
36919af5a38SHeinrich Kuhn  * is based on a unix socket and requests usually received by a kernel char
37019af5a38SHeinrich Kuhn  * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
37119af5a38SHeinrich Kuhn  * can be executed with a wrapper library and LD_LIBRARY being completely
37219af5a38SHeinrich Kuhn  * unaware of the CPP bridge performing the NFP kernel char driver for CPP
37319af5a38SHeinrich Kuhn  * accesses.
37419af5a38SHeinrich Kuhn  */
375b1880421SChaoyong He static int
37619af5a38SHeinrich Kuhn nfp_cpp_bridge_service_func(void *args)
37719af5a38SHeinrich Kuhn {
37819af5a38SHeinrich Kuhn 	struct sockaddr address;
379bab0e6f4SChaoyong He 	struct nfp_cpp *cpp;
380bab0e6f4SChaoyong He 	struct nfp_pf_dev *pf_dev;
38119af5a38SHeinrich Kuhn 	int sockfd, datafd, op, ret;
382a5b876a5SChaoyong He 	struct timeval timeout = {1, 0};
38319af5a38SHeinrich Kuhn 
38419af5a38SHeinrich Kuhn 	unlink("/tmp/nfp_cpp");
38519af5a38SHeinrich Kuhn 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
38619af5a38SHeinrich Kuhn 	if (sockfd < 0) {
38719af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: socket creation error. Service failed\n",
38819af5a38SHeinrich Kuhn 			__func__);
38919af5a38SHeinrich Kuhn 		return -EIO;
39019af5a38SHeinrich Kuhn 	}
39119af5a38SHeinrich Kuhn 
392a5b876a5SChaoyong He 	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
393a5b876a5SChaoyong He 
39419af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
39519af5a38SHeinrich Kuhn 
39619af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
39719af5a38SHeinrich Kuhn 	strcpy(address.sa_data, "/tmp/nfp_cpp");
39819af5a38SHeinrich Kuhn 
39919af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
40019af5a38SHeinrich Kuhn 		   sizeof(struct sockaddr));
40119af5a38SHeinrich Kuhn 	if (ret < 0) {
40219af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: bind error (%d). Service failed\n",
40319af5a38SHeinrich Kuhn 				  __func__, errno);
40419af5a38SHeinrich Kuhn 		close(sockfd);
40519af5a38SHeinrich Kuhn 		return ret;
40619af5a38SHeinrich Kuhn 	}
40719af5a38SHeinrich Kuhn 
40819af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
40919af5a38SHeinrich Kuhn 	if (ret < 0) {
41019af5a38SHeinrich Kuhn 		RTE_LOG(ERR, PMD, "%s: listen error(%d). Service failed\n",
41119af5a38SHeinrich Kuhn 				  __func__, errno);
41219af5a38SHeinrich Kuhn 		close(sockfd);
41319af5a38SHeinrich Kuhn 		return ret;
41419af5a38SHeinrich Kuhn 	}
41519af5a38SHeinrich Kuhn 
416bab0e6f4SChaoyong He 	pf_dev = args;
417bab0e6f4SChaoyong He 	cpp = pf_dev->cpp;
418bab0e6f4SChaoyong He 	while (rte_service_runstate_get(pf_dev->cpp_bridge_id) != 0) {
41919af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
42019af5a38SHeinrich Kuhn 		if (datafd < 0) {
421a5b876a5SChaoyong He 			if (errno == EAGAIN || errno == EWOULDBLOCK)
422a5b876a5SChaoyong He 				continue;
423a5b876a5SChaoyong He 
42419af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: accept call error (%d)\n",
42519af5a38SHeinrich Kuhn 					  __func__, errno);
42619af5a38SHeinrich Kuhn 			RTE_LOG(ERR, PMD, "%s: service failed\n", __func__);
42719af5a38SHeinrich Kuhn 			close(sockfd);
42819af5a38SHeinrich Kuhn 			return -EIO;
42919af5a38SHeinrich Kuhn 		}
43019af5a38SHeinrich Kuhn 
43119af5a38SHeinrich Kuhn 		while (1) {
43219af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
43319af5a38SHeinrich Kuhn 			if (ret <= 0) {
43419af5a38SHeinrich Kuhn 				PMD_CPP_LOG(DEBUG, "%s: socket close\n",
43519af5a38SHeinrich Kuhn 						   __func__);
43619af5a38SHeinrich Kuhn 				break;
43719af5a38SHeinrich Kuhn 			}
43819af5a38SHeinrich Kuhn 
43919af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: getting op %u\n", __func__, op);
44019af5a38SHeinrich Kuhn 
44119af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
44219af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
44319af5a38SHeinrich Kuhn 
44419af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
44519af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
44619af5a38SHeinrich Kuhn 
44719af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
44819af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
44919af5a38SHeinrich Kuhn 
45019af5a38SHeinrich Kuhn 			if (op == 0)
45119af5a38SHeinrich Kuhn 				break;
45219af5a38SHeinrich Kuhn 		}
45319af5a38SHeinrich Kuhn 		close(datafd);
45419af5a38SHeinrich Kuhn 	}
45519af5a38SHeinrich Kuhn 	close(sockfd);
45619af5a38SHeinrich Kuhn 
45719af5a38SHeinrich Kuhn 	return 0;
45819af5a38SHeinrich Kuhn }
45919af5a38SHeinrich Kuhn /*
46019af5a38SHeinrich Kuhn  * Local variables:
46119af5a38SHeinrich Kuhn  * c-file-style: "Linux"
46219af5a38SHeinrich Kuhn  * indent-tabs-mode: t
46319af5a38SHeinrich Kuhn  * End:
46419af5a38SHeinrich Kuhn  */
465