xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision f4d24fe971b207d34f299bc82b0475fb8d36b867)
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 
8f1523facSChaoyong He #include "nfp_cpp_bridge.h"
9f1523facSChaoyong He 
108987de81SChaoyong He #include <unistd.h>
118987de81SChaoyong He #include <sys/ioctl.h>
128987de81SChaoyong He 
1319af5a38SHeinrich Kuhn #include <rte_service_component.h>
1419af5a38SHeinrich Kuhn 
1519af5a38SHeinrich Kuhn #include "nfpcore/nfp_cpp.h"
168d7a59f1SHeinrich Kuhn #include "nfp_logs.h"
17f1523facSChaoyong He 
18f1523facSChaoyong He #define NFP_CPP_MEMIO_BOUNDARY    (1 << 20)
19f1523facSChaoyong He #define NFP_BRIDGE_OP_READ        20
20f1523facSChaoyong He #define NFP_BRIDGE_OP_WRITE       30
21f1523facSChaoyong He #define NFP_BRIDGE_OP_IOCTL       40
22f1523facSChaoyong He 
23f1523facSChaoyong He #define NFP_IOCTL 'n'
24f1523facSChaoyong He #define NFP_IOCTL_CPP_IDENTIFICATION _IOW(NFP_IOCTL, 0x8f, uint32_t)
2519af5a38SHeinrich Kuhn 
2619af5a38SHeinrich Kuhn /* Prototypes */
2719af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_write(int sockfd, struct nfp_cpp *cpp);
2819af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_read(int sockfd, struct nfp_cpp *cpp);
2919af5a38SHeinrich Kuhn static int nfp_cpp_bridge_serve_ioctl(int sockfd, struct nfp_cpp *cpp);
30b1880421SChaoyong He static int nfp_cpp_bridge_service_func(void *args);
3119af5a38SHeinrich Kuhn 
32b1880421SChaoyong He int
33b1880421SChaoyong He nfp_map_service(uint32_t service_id)
3419af5a38SHeinrich Kuhn {
35b1880421SChaoyong He 	int32_t ret;
36b1880421SChaoyong He 	uint32_t slcore = 0;
37b1880421SChaoyong He 	int32_t slcore_count;
38b1880421SChaoyong He 	uint8_t service_count;
39b1880421SChaoyong He 	const char *service_name;
40b1880421SChaoyong He 	uint32_t slcore_array[RTE_MAX_LCORE];
41b1880421SChaoyong He 	uint8_t min_service_count = UINT8_MAX;
4219af5a38SHeinrich Kuhn 
43b1880421SChaoyong He 	slcore_count = rte_service_lcore_list(slcore_array, RTE_MAX_LCORE);
44b1880421SChaoyong He 	if (slcore_count <= 0) {
45b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "No service cores found");
46b1880421SChaoyong He 		return -ENOENT;
47b1880421SChaoyong He 	}
4819af5a38SHeinrich Kuhn 
49b1880421SChaoyong He 	/*
50b1880421SChaoyong He 	 * Find a service core with the least number of services already
51b1880421SChaoyong He 	 * registered to it
52b1880421SChaoyong He 	 */
53b1880421SChaoyong He 	while (slcore_count--) {
54b1880421SChaoyong He 		service_count = rte_service_lcore_count_services(slcore_array[slcore_count]);
55b1880421SChaoyong He 		if (service_count < min_service_count) {
56b1880421SChaoyong He 			slcore = slcore_array[slcore_count];
57b1880421SChaoyong He 			min_service_count = service_count;
58b1880421SChaoyong He 		}
59b1880421SChaoyong He 	}
60b1880421SChaoyong He 
61b1880421SChaoyong He 	service_name = rte_service_get_name(service_id);
62b1880421SChaoyong He 	PMD_INIT_LOG(INFO, "Mapping service %s to core %u", service_name, slcore);
63b1880421SChaoyong He 
64b1880421SChaoyong He 	ret = rte_service_map_lcore_set(service_id, slcore, 1);
65b1880421SChaoyong He 	if (ret != 0) {
66b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "Could not map flower service");
67b1880421SChaoyong He 		return -ENOENT;
68b1880421SChaoyong He 	}
69b1880421SChaoyong He 
70b1880421SChaoyong He 	rte_service_runstate_set(service_id, 1);
71b1880421SChaoyong He 	rte_service_component_runstate_set(service_id, 1);
72b1880421SChaoyong He 	rte_service_lcore_start(slcore);
73c01e5c0cSChaoyong He 	if (rte_service_may_be_active(slcore) != 0)
74b1880421SChaoyong He 		PMD_INIT_LOG(INFO, "The service %s is running", service_name);
7519af5a38SHeinrich Kuhn 	else
76b1880421SChaoyong He 		PMD_INIT_LOG(ERR, "The service %s is not running", service_name);
77b1880421SChaoyong He 
78b1880421SChaoyong He 	return 0;
79b1880421SChaoyong He }
80b1880421SChaoyong He 
81b1880421SChaoyong He int
82bab0e6f4SChaoyong He nfp_enable_cpp_service(struct nfp_pf_dev *pf_dev)
83b1880421SChaoyong He {
84b1880421SChaoyong He 	int ret;
85b1880421SChaoyong He 	uint32_t service_id = 0;
86b1880421SChaoyong He 	struct rte_service_spec cpp_service = {
87b1880421SChaoyong He 		.name         = "nfp_cpp_service",
88b1880421SChaoyong He 		.callback     = nfp_cpp_bridge_service_func,
89b1880421SChaoyong He 	};
90b1880421SChaoyong He 
91bab0e6f4SChaoyong He 	cpp_service.callback_userdata = (void *)pf_dev;
92b1880421SChaoyong He 
93b1880421SChaoyong He 	/* Register the cpp service */
94b1880421SChaoyong He 	ret = rte_service_component_register(&cpp_service, &service_id);
95b1880421SChaoyong He 	if (ret != 0) {
96b1880421SChaoyong He 		PMD_INIT_LOG(WARNING, "Could not register nfp cpp service");
97b1880421SChaoyong He 		return -EINVAL;
98b1880421SChaoyong He 	}
99b1880421SChaoyong He 
100bab0e6f4SChaoyong He 	pf_dev->cpp_bridge_id = service_id;
101b1880421SChaoyong He 	PMD_INIT_LOG(INFO, "NFP cpp service registered");
102b1880421SChaoyong He 
103b1880421SChaoyong He 	/* Map it to available service core*/
104b1880421SChaoyong He 	ret = nfp_map_service(service_id);
105b1880421SChaoyong He 	if (ret != 0) {
106b1880421SChaoyong He 		PMD_INIT_LOG(DEBUG, "Could not map nfp cpp service");
107b1880421SChaoyong He 		return -EINVAL;
108b1880421SChaoyong He 	}
109b1880421SChaoyong He 
110b1880421SChaoyong He 	return 0;
11119af5a38SHeinrich Kuhn }
11219af5a38SHeinrich Kuhn 
11319af5a38SHeinrich Kuhn /*
11419af5a38SHeinrich Kuhn  * Serving a write request to NFP from host programs. The request
11519af5a38SHeinrich Kuhn  * sends the write size and the CPP target. The bridge makes use
11619af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup.
11719af5a38SHeinrich Kuhn  */
11819af5a38SHeinrich Kuhn static int
119*f4d24fe9SChaoyong He nfp_cpp_bridge_serve_write(int sockfd,
120*f4d24fe9SChaoyong He 		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);
164cbcbfd73SJames Hershaw 		if (area == NULL) {
16554fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc fail");
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) {
17254fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
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) {
186*f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when receiving, %d of %zu",
18754fdb550SChaoyong He 						err, count);
18819af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
18919af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
19019af5a38SHeinrich Kuhn 				return -EIO;
19119af5a38SHeinrich Kuhn 			}
19219af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
19319af5a38SHeinrich Kuhn 			if (err < 0) {
19454fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_write error");
19519af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
19619af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
19719af5a38SHeinrich Kuhn 				return -EIO;
19819af5a38SHeinrich Kuhn 			}
19919af5a38SHeinrich Kuhn 		}
20019af5a38SHeinrich Kuhn 
20119af5a38SHeinrich Kuhn 		nfp_offset += pos;
20219af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
20319af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
20419af5a38SHeinrich Kuhn 
20519af5a38SHeinrich Kuhn 		count -= pos;
20619af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
20719af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
20819af5a38SHeinrich Kuhn 	}
20919af5a38SHeinrich Kuhn 
21019af5a38SHeinrich Kuhn 	return 0;
21119af5a38SHeinrich Kuhn }
21219af5a38SHeinrich Kuhn 
21319af5a38SHeinrich Kuhn /*
21419af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
21519af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
21619af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
21719af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
21819af5a38SHeinrich Kuhn  */
21919af5a38SHeinrich Kuhn static int
220*f4d24fe9SChaoyong He nfp_cpp_bridge_serve_read(int sockfd,
221*f4d24fe9SChaoyong He 		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);
264cbcbfd73SJames Hershaw 		if (area == NULL) {
26554fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc failed");
26619af5a38SHeinrich Kuhn 			return -EIO;
26719af5a38SHeinrich Kuhn 		}
26819af5a38SHeinrich Kuhn 
26919af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
27019af5a38SHeinrich Kuhn 		if (err < 0) {
27154fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
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) {
28354fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_read error");
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) {
293*f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when sending: %d of %zu",
29454fdb550SChaoyong He 						err, count);
29519af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
29619af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
29719af5a38SHeinrich Kuhn 				return -EIO;
29819af5a38SHeinrich Kuhn 			}
29919af5a38SHeinrich Kuhn 		}
30019af5a38SHeinrich Kuhn 
30119af5a38SHeinrich Kuhn 		nfp_offset += pos;
30219af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
30319af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
30419af5a38SHeinrich Kuhn 
30519af5a38SHeinrich Kuhn 		count -= pos;
30619af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
30719af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
30819af5a38SHeinrich Kuhn 	}
30919af5a38SHeinrich Kuhn 	return 0;
31019af5a38SHeinrich Kuhn }
31119af5a38SHeinrich Kuhn 
31219af5a38SHeinrich Kuhn /*
31319af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
31419af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
31519af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
31619af5a38SHeinrich Kuhn  * does not require any CPP access at all.
31719af5a38SHeinrich Kuhn  */
31819af5a38SHeinrich Kuhn static int
319*f4d24fe9SChaoyong He nfp_cpp_bridge_serve_ioctl(int sockfd,
320*f4d24fe9SChaoyong He 		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) {
32854fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
32919af5a38SHeinrich Kuhn 		return -EIO;
33019af5a38SHeinrich Kuhn 	}
33119af5a38SHeinrich Kuhn 
33219af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
33319af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
33454fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "unknown cmd %d", cmd);
33519af5a38SHeinrich Kuhn 		return -EINVAL;
33619af5a38SHeinrich Kuhn 	}
33719af5a38SHeinrich Kuhn 
33819af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
33919af5a38SHeinrich Kuhn 	if (err != 4) {
34054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
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) {
35054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "error writing to socket");
35119af5a38SHeinrich Kuhn 		return -EIO;
35219af5a38SHeinrich Kuhn 	}
35319af5a38SHeinrich Kuhn 
354ff627b74SChaoyong He 	tmp = nfp_cpp_interface(cpp);
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) {
36054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "error writing to socket");
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) {
38754fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "socket creation error. Service failed");
38819af5a38SHeinrich Kuhn 		return -EIO;
38919af5a38SHeinrich Kuhn 	}
39019af5a38SHeinrich Kuhn 
391a5b876a5SChaoyong He 	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
392a5b876a5SChaoyong He 
39319af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
39419af5a38SHeinrich Kuhn 
39519af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
39619af5a38SHeinrich Kuhn 	strcpy(address.sa_data, "/tmp/nfp_cpp");
39719af5a38SHeinrich Kuhn 
39819af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
39919af5a38SHeinrich Kuhn 			sizeof(struct sockaddr));
40019af5a38SHeinrich Kuhn 	if (ret < 0) {
40154fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "bind error (%d). Service failed", errno);
40219af5a38SHeinrich Kuhn 		close(sockfd);
40319af5a38SHeinrich Kuhn 		return ret;
40419af5a38SHeinrich Kuhn 	}
40519af5a38SHeinrich Kuhn 
40619af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
40719af5a38SHeinrich Kuhn 	if (ret < 0) {
40854fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "listen error(%d). Service failed", errno);
40919af5a38SHeinrich Kuhn 		close(sockfd);
41019af5a38SHeinrich Kuhn 		return ret;
41119af5a38SHeinrich Kuhn 	}
41219af5a38SHeinrich Kuhn 
413bab0e6f4SChaoyong He 	pf_dev = args;
414bab0e6f4SChaoyong He 	cpp = pf_dev->cpp;
415bab0e6f4SChaoyong He 	while (rte_service_runstate_get(pf_dev->cpp_bridge_id) != 0) {
41619af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
41719af5a38SHeinrich Kuhn 		if (datafd < 0) {
418a5b876a5SChaoyong He 			if (errno == EAGAIN || errno == EWOULDBLOCK)
419a5b876a5SChaoyong He 				continue;
420a5b876a5SChaoyong He 
42154fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "accept call error (%d)", errno);
42254fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "service failed");
42319af5a38SHeinrich Kuhn 			close(sockfd);
42419af5a38SHeinrich Kuhn 			return -EIO;
42519af5a38SHeinrich Kuhn 		}
42619af5a38SHeinrich Kuhn 
42719af5a38SHeinrich Kuhn 		while (1) {
42819af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
42919af5a38SHeinrich Kuhn 			if (ret <= 0) {
430*f4d24fe9SChaoyong He 				PMD_CPP_LOG(DEBUG, "%s: socket close\n", __func__);
43119af5a38SHeinrich Kuhn 				break;
43219af5a38SHeinrich Kuhn 			}
43319af5a38SHeinrich Kuhn 
43419af5a38SHeinrich Kuhn 			PMD_CPP_LOG(DEBUG, "%s: getting op %u\n", __func__, op);
43519af5a38SHeinrich Kuhn 
43619af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
43719af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
43819af5a38SHeinrich Kuhn 
43919af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
44019af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
44119af5a38SHeinrich Kuhn 
44219af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
44319af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
44419af5a38SHeinrich Kuhn 
44519af5a38SHeinrich Kuhn 			if (op == 0)
44619af5a38SHeinrich Kuhn 				break;
44719af5a38SHeinrich Kuhn 		}
44819af5a38SHeinrich Kuhn 		close(datafd);
44919af5a38SHeinrich Kuhn 	}
45019af5a38SHeinrich Kuhn 	close(sockfd);
45119af5a38SHeinrich Kuhn 
45219af5a38SHeinrich Kuhn 	return 0;
45319af5a38SHeinrich Kuhn }
454