xref: /dpdk/drivers/net/nfp/nfp_cpp_bridge.c (revision 030b2b19dce19c9a34d4d41fc514dc4cb0f775c0)
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
119f4d24fe9SChaoyong He nfp_cpp_bridge_serve_write(int sockfd,
120f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
12119af5a38SHeinrich Kuhn {
12249952141SChaoyong He 	int err;
12349952141SChaoyong He 	off_t offset;
12449952141SChaoyong He 	uint32_t pos;
12549952141SChaoyong He 	uint32_t len;
12649952141SChaoyong He 	size_t count;
12749952141SChaoyong He 	size_t curlen;
12849952141SChaoyong He 	uint32_t cpp_id;
12949952141SChaoyong He 	off_t nfp_offset;
13019af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
13149952141SChaoyong He 	struct nfp_cpp_area *area;
13219af5a38SHeinrich Kuhn 
133*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu", __func__,
13419af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
13519af5a38SHeinrich Kuhn 
13619af5a38SHeinrich Kuhn 	/* Reading the count param */
13719af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
13819af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
13919af5a38SHeinrich Kuhn 		return -EINVAL;
14019af5a38SHeinrich Kuhn 
14119af5a38SHeinrich Kuhn 	curlen = count;
14219af5a38SHeinrich Kuhn 
14319af5a38SHeinrich Kuhn 	/* Reading the offset param */
14419af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
14519af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
14619af5a38SHeinrich Kuhn 		return -EINVAL;
14719af5a38SHeinrich Kuhn 
14819af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
14919af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
15019af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
15119af5a38SHeinrich Kuhn 
152*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd", __func__, count,
15319af5a38SHeinrich Kuhn 			offset);
154*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd", __func__,
15519af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
15619af5a38SHeinrich Kuhn 
15719af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
15819af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
15919af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
16019af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
16119af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
16219af5a38SHeinrich Kuhn 	}
16319af5a38SHeinrich Kuhn 
16419af5a38SHeinrich Kuhn 	while (count > 0) {
165*030b2b19SChaoyong He 		/* Configure a CPP PCIe2CPP BAR for mapping the CPP target */
16619af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
16719af5a38SHeinrich Kuhn 				nfp_offset, curlen);
168cbcbfd73SJames Hershaw 		if (area == NULL) {
16954fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc fail");
17019af5a38SHeinrich Kuhn 			return -EIO;
17119af5a38SHeinrich Kuhn 		}
17219af5a38SHeinrich Kuhn 
173*030b2b19SChaoyong He 		/* Mapping the target */
17419af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
17519af5a38SHeinrich Kuhn 		if (err < 0) {
17654fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
17719af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
17819af5a38SHeinrich Kuhn 			return -EIO;
17919af5a38SHeinrich Kuhn 		}
18019af5a38SHeinrich Kuhn 
18119af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
18219af5a38SHeinrich Kuhn 			len = curlen - pos;
18319af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
18419af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
18519af5a38SHeinrich Kuhn 
186*030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: Receive %u of %zu", __func__,
18719af5a38SHeinrich Kuhn 					len, count);
18819af5a38SHeinrich Kuhn 			err = recv(sockfd, tmpbuf, len, MSG_WAITALL);
18919af5a38SHeinrich Kuhn 			if (err != (int)len) {
190f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when receiving, %d of %zu",
19154fdb550SChaoyong He 						err, count);
19219af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
19319af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
19419af5a38SHeinrich Kuhn 				return -EIO;
19519af5a38SHeinrich Kuhn 			}
19619af5a38SHeinrich Kuhn 			err = nfp_cpp_area_write(area, pos, tmpbuf, len);
19719af5a38SHeinrich Kuhn 			if (err < 0) {
19854fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_write error");
19919af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
20019af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
20119af5a38SHeinrich Kuhn 				return -EIO;
20219af5a38SHeinrich Kuhn 			}
20319af5a38SHeinrich Kuhn 		}
20419af5a38SHeinrich Kuhn 
20519af5a38SHeinrich Kuhn 		nfp_offset += pos;
20619af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
20719af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
20819af5a38SHeinrich Kuhn 
20919af5a38SHeinrich Kuhn 		count -= pos;
21019af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
21119af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
21219af5a38SHeinrich Kuhn 	}
21319af5a38SHeinrich Kuhn 
21419af5a38SHeinrich Kuhn 	return 0;
21519af5a38SHeinrich Kuhn }
21619af5a38SHeinrich Kuhn 
21719af5a38SHeinrich Kuhn /*
21819af5a38SHeinrich Kuhn  * Serving a read request to NFP from host programs. The request
21919af5a38SHeinrich Kuhn  * sends the read size and the CPP target. The bridge makes use
22019af5a38SHeinrich Kuhn  * of CPP interface handler configured by the PMD setup. The read
22119af5a38SHeinrich Kuhn  * data is sent to the requester using the same socket.
22219af5a38SHeinrich Kuhn  */
22319af5a38SHeinrich Kuhn static int
224f4d24fe9SChaoyong He nfp_cpp_bridge_serve_read(int sockfd,
225f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
22619af5a38SHeinrich Kuhn {
22749952141SChaoyong He 	int err;
22849952141SChaoyong He 	off_t offset;
22949952141SChaoyong He 	uint32_t pos;
23049952141SChaoyong He 	uint32_t len;
23149952141SChaoyong He 	size_t count;
23249952141SChaoyong He 	size_t curlen;
23349952141SChaoyong He 	uint32_t cpp_id;
23449952141SChaoyong He 	off_t nfp_offset;
23519af5a38SHeinrich Kuhn 	uint32_t tmpbuf[16];
23649952141SChaoyong He 	struct nfp_cpp_area *area;
23719af5a38SHeinrich Kuhn 
238*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: offset size %zu, count_size: %zu", __func__,
23919af5a38SHeinrich Kuhn 			sizeof(off_t), sizeof(size_t));
24019af5a38SHeinrich Kuhn 
24119af5a38SHeinrich Kuhn 	/* Reading the count param */
24219af5a38SHeinrich Kuhn 	err = recv(sockfd, &count, sizeof(off_t), 0);
24319af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
24419af5a38SHeinrich Kuhn 		return -EINVAL;
24519af5a38SHeinrich Kuhn 
24619af5a38SHeinrich Kuhn 	curlen = count;
24719af5a38SHeinrich Kuhn 
24819af5a38SHeinrich Kuhn 	/* Reading the offset param */
24919af5a38SHeinrich Kuhn 	err = recv(sockfd, &offset, sizeof(off_t), 0);
25019af5a38SHeinrich Kuhn 	if (err != sizeof(off_t))
25119af5a38SHeinrich Kuhn 		return -EINVAL;
25219af5a38SHeinrich Kuhn 
25319af5a38SHeinrich Kuhn 	/* Obtain target's CPP ID and offset in target */
25419af5a38SHeinrich Kuhn 	cpp_id = (offset >> 40) << 8;
25519af5a38SHeinrich Kuhn 	nfp_offset = offset & ((1ull << 40) - 1);
25619af5a38SHeinrich Kuhn 
257*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: count %zu and offset %jd", __func__, count,
25819af5a38SHeinrich Kuhn 			offset);
259*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: cpp_id %08x and nfp_offset %jd", __func__,
26019af5a38SHeinrich Kuhn 			cpp_id, nfp_offset);
26119af5a38SHeinrich Kuhn 
26219af5a38SHeinrich Kuhn 	/* Adjust length if not aligned */
26319af5a38SHeinrich Kuhn 	if (((nfp_offset + (off_t)count - 1) & ~(NFP_CPP_MEMIO_BOUNDARY - 1)) !=
26419af5a38SHeinrich Kuhn 			(nfp_offset & ~(NFP_CPP_MEMIO_BOUNDARY - 1))) {
26519af5a38SHeinrich Kuhn 		curlen = NFP_CPP_MEMIO_BOUNDARY -
26619af5a38SHeinrich Kuhn 				(nfp_offset & (NFP_CPP_MEMIO_BOUNDARY - 1));
26719af5a38SHeinrich Kuhn 	}
26819af5a38SHeinrich Kuhn 
26919af5a38SHeinrich Kuhn 	while (count > 0) {
27019af5a38SHeinrich Kuhn 		area = nfp_cpp_area_alloc_with_name(cpp, cpp_id, "nfp.cdev",
27119af5a38SHeinrich Kuhn 				nfp_offset, curlen);
272cbcbfd73SJames Hershaw 		if (area == NULL) {
27354fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area alloc failed");
27419af5a38SHeinrich Kuhn 			return -EIO;
27519af5a38SHeinrich Kuhn 		}
27619af5a38SHeinrich Kuhn 
27719af5a38SHeinrich Kuhn 		err = nfp_cpp_area_acquire(area);
27819af5a38SHeinrich Kuhn 		if (err < 0) {
27954fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "area acquire failed");
28019af5a38SHeinrich Kuhn 			nfp_cpp_area_free(area);
28119af5a38SHeinrich Kuhn 			return -EIO;
28219af5a38SHeinrich Kuhn 		}
28319af5a38SHeinrich Kuhn 
28419af5a38SHeinrich Kuhn 		for (pos = 0; pos < curlen; pos += len) {
28519af5a38SHeinrich Kuhn 			len = curlen - pos;
28619af5a38SHeinrich Kuhn 			if (len > sizeof(tmpbuf))
28719af5a38SHeinrich Kuhn 				len = sizeof(tmpbuf);
28819af5a38SHeinrich Kuhn 
28919af5a38SHeinrich Kuhn 			err = nfp_cpp_area_read(area, pos, tmpbuf, len);
29019af5a38SHeinrich Kuhn 			if (err < 0) {
29154fdb550SChaoyong He 				PMD_CPP_LOG(ERR, "nfp_cpp_area_read error");
29219af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
29319af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
29419af5a38SHeinrich Kuhn 				return -EIO;
29519af5a38SHeinrich Kuhn 			}
296*030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: sending %u of %zu", __func__,
29719af5a38SHeinrich Kuhn 					len, count);
29819af5a38SHeinrich Kuhn 
29919af5a38SHeinrich Kuhn 			err = send(sockfd, tmpbuf, len, 0);
30019af5a38SHeinrich Kuhn 			if (err != (int)len) {
301f4d24fe9SChaoyong He 				PMD_CPP_LOG(ERR, "error when sending: %d of %zu",
30254fdb550SChaoyong He 						err, count);
30319af5a38SHeinrich Kuhn 				nfp_cpp_area_release(area);
30419af5a38SHeinrich Kuhn 				nfp_cpp_area_free(area);
30519af5a38SHeinrich Kuhn 				return -EIO;
30619af5a38SHeinrich Kuhn 			}
30719af5a38SHeinrich Kuhn 		}
30819af5a38SHeinrich Kuhn 
30919af5a38SHeinrich Kuhn 		nfp_offset += pos;
31019af5a38SHeinrich Kuhn 		nfp_cpp_area_release(area);
31119af5a38SHeinrich Kuhn 		nfp_cpp_area_free(area);
31219af5a38SHeinrich Kuhn 
31319af5a38SHeinrich Kuhn 		count -= pos;
31419af5a38SHeinrich Kuhn 		curlen = (count > NFP_CPP_MEMIO_BOUNDARY) ?
31519af5a38SHeinrich Kuhn 				NFP_CPP_MEMIO_BOUNDARY : count;
31619af5a38SHeinrich Kuhn 	}
31719af5a38SHeinrich Kuhn 	return 0;
31819af5a38SHeinrich Kuhn }
31919af5a38SHeinrich Kuhn 
32019af5a38SHeinrich Kuhn /*
32119af5a38SHeinrich Kuhn  * Serving a ioctl command from host NFP tools. This usually goes to
32219af5a38SHeinrich Kuhn  * a kernel driver char driver but it is not available when the PF is
32319af5a38SHeinrich Kuhn  * bound to the PMD. Currently just one ioctl command is served and it
32419af5a38SHeinrich Kuhn  * does not require any CPP access at all.
32519af5a38SHeinrich Kuhn  */
32619af5a38SHeinrich Kuhn static int
327f4d24fe9SChaoyong He nfp_cpp_bridge_serve_ioctl(int sockfd,
328f4d24fe9SChaoyong He 		struct nfp_cpp *cpp)
32919af5a38SHeinrich Kuhn {
33019af5a38SHeinrich Kuhn 	int err;
33149952141SChaoyong He 	uint32_t cmd;
33249952141SChaoyong He 	uint32_t tmp;
33349952141SChaoyong He 	uint32_t ident_size;
33419af5a38SHeinrich Kuhn 
33519af5a38SHeinrich Kuhn 	/* Reading now the IOCTL command */
33619af5a38SHeinrich Kuhn 	err = recv(sockfd, &cmd, 4, 0);
33719af5a38SHeinrich Kuhn 	if (err != 4) {
33854fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
33919af5a38SHeinrich Kuhn 		return -EIO;
34019af5a38SHeinrich Kuhn 	}
34119af5a38SHeinrich Kuhn 
34219af5a38SHeinrich Kuhn 	/* Only supporting NFP_IOCTL_CPP_IDENTIFICATION */
34319af5a38SHeinrich Kuhn 	if (cmd != NFP_IOCTL_CPP_IDENTIFICATION) {
34454fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "unknown cmd %d", cmd);
34519af5a38SHeinrich Kuhn 		return -EINVAL;
34619af5a38SHeinrich Kuhn 	}
34719af5a38SHeinrich Kuhn 
34819af5a38SHeinrich Kuhn 	err = recv(sockfd, &ident_size, 4, 0);
34919af5a38SHeinrich Kuhn 	if (err != 4) {
35054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "read error from socket");
35119af5a38SHeinrich Kuhn 		return -EIO;
35219af5a38SHeinrich Kuhn 	}
35319af5a38SHeinrich Kuhn 
35419af5a38SHeinrich Kuhn 	tmp = nfp_cpp_model(cpp);
35519af5a38SHeinrich Kuhn 
356*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: sending NFP model %08x", __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 
364ff627b74SChaoyong He 	tmp = nfp_cpp_interface(cpp);
36519af5a38SHeinrich Kuhn 
366*030b2b19SChaoyong He 	PMD_CPP_LOG(DEBUG, "%s: sending NFP interface %08x", __func__, tmp);
36719af5a38SHeinrich Kuhn 
36819af5a38SHeinrich Kuhn 	err = send(sockfd, &tmp, 4, 0);
36919af5a38SHeinrich Kuhn 	if (err != 4) {
37054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "error writing to socket");
37119af5a38SHeinrich Kuhn 		return -EIO;
37219af5a38SHeinrich Kuhn 	}
37319af5a38SHeinrich Kuhn 
37419af5a38SHeinrich Kuhn 	return 0;
37519af5a38SHeinrich Kuhn }
37619af5a38SHeinrich Kuhn 
37719af5a38SHeinrich Kuhn /*
37819af5a38SHeinrich Kuhn  * This is the code to be executed by a service core. The CPP bridge interface
37919af5a38SHeinrich Kuhn  * is based on a unix socket and requests usually received by a kernel char
38019af5a38SHeinrich Kuhn  * driver, read, write and ioctl, are handled by the CPP bridge. NFP host tools
38119af5a38SHeinrich Kuhn  * can be executed with a wrapper library and LD_LIBRARY being completely
38219af5a38SHeinrich Kuhn  * unaware of the CPP bridge performing the NFP kernel char driver for CPP
38319af5a38SHeinrich Kuhn  * accesses.
38419af5a38SHeinrich Kuhn  */
385b1880421SChaoyong He static int
38619af5a38SHeinrich Kuhn nfp_cpp_bridge_service_func(void *args)
38719af5a38SHeinrich Kuhn {
38849952141SChaoyong He 	int op;
38949952141SChaoyong He 	int ret;
39049952141SChaoyong He 	int sockfd;
39149952141SChaoyong He 	int datafd;
392bab0e6f4SChaoyong He 	struct nfp_cpp *cpp;
39349952141SChaoyong He 	struct sockaddr address;
394bab0e6f4SChaoyong He 	struct nfp_pf_dev *pf_dev;
395a5b876a5SChaoyong He 	struct timeval timeout = {1, 0};
39619af5a38SHeinrich Kuhn 
39719af5a38SHeinrich Kuhn 	unlink("/tmp/nfp_cpp");
39819af5a38SHeinrich Kuhn 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
39919af5a38SHeinrich Kuhn 	if (sockfd < 0) {
40054fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "socket creation error. Service failed");
40119af5a38SHeinrich Kuhn 		return -EIO;
40219af5a38SHeinrich Kuhn 	}
40319af5a38SHeinrich Kuhn 
404a5b876a5SChaoyong He 	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
405a5b876a5SChaoyong He 
40619af5a38SHeinrich Kuhn 	memset(&address, 0, sizeof(struct sockaddr));
40719af5a38SHeinrich Kuhn 
40819af5a38SHeinrich Kuhn 	address.sa_family = AF_UNIX;
40919af5a38SHeinrich Kuhn 	strcpy(address.sa_data, "/tmp/nfp_cpp");
41019af5a38SHeinrich Kuhn 
41119af5a38SHeinrich Kuhn 	ret = bind(sockfd, (const struct sockaddr *)&address,
41219af5a38SHeinrich Kuhn 			sizeof(struct sockaddr));
41319af5a38SHeinrich Kuhn 	if (ret < 0) {
41454fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "bind error (%d). Service failed", errno);
41519af5a38SHeinrich Kuhn 		close(sockfd);
41619af5a38SHeinrich Kuhn 		return ret;
41719af5a38SHeinrich Kuhn 	}
41819af5a38SHeinrich Kuhn 
41919af5a38SHeinrich Kuhn 	ret = listen(sockfd, 20);
42019af5a38SHeinrich Kuhn 	if (ret < 0) {
42154fdb550SChaoyong He 		PMD_CPP_LOG(ERR, "listen error(%d). Service failed", errno);
42219af5a38SHeinrich Kuhn 		close(sockfd);
42319af5a38SHeinrich Kuhn 		return ret;
42419af5a38SHeinrich Kuhn 	}
42519af5a38SHeinrich Kuhn 
426bab0e6f4SChaoyong He 	pf_dev = args;
427bab0e6f4SChaoyong He 	cpp = pf_dev->cpp;
428bab0e6f4SChaoyong He 	while (rte_service_runstate_get(pf_dev->cpp_bridge_id) != 0) {
42919af5a38SHeinrich Kuhn 		datafd = accept(sockfd, NULL, NULL);
43019af5a38SHeinrich Kuhn 		if (datafd < 0) {
431a5b876a5SChaoyong He 			if (errno == EAGAIN || errno == EWOULDBLOCK)
432a5b876a5SChaoyong He 				continue;
433a5b876a5SChaoyong He 
43454fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "accept call error (%d)", errno);
43554fdb550SChaoyong He 			PMD_CPP_LOG(ERR, "service failed");
43619af5a38SHeinrich Kuhn 			close(sockfd);
43719af5a38SHeinrich Kuhn 			return -EIO;
43819af5a38SHeinrich Kuhn 		}
43919af5a38SHeinrich Kuhn 
44019af5a38SHeinrich Kuhn 		while (1) {
44119af5a38SHeinrich Kuhn 			ret = recv(datafd, &op, 4, 0);
44219af5a38SHeinrich Kuhn 			if (ret <= 0) {
443*030b2b19SChaoyong He 				PMD_CPP_LOG(DEBUG, "%s: socket close", __func__);
44419af5a38SHeinrich Kuhn 				break;
44519af5a38SHeinrich Kuhn 			}
44619af5a38SHeinrich Kuhn 
447*030b2b19SChaoyong He 			PMD_CPP_LOG(DEBUG, "%s: getting op %u", __func__, op);
44819af5a38SHeinrich Kuhn 
44919af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_READ)
45019af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_read(datafd, cpp);
45119af5a38SHeinrich Kuhn 
45219af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_WRITE)
45319af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_write(datafd, cpp);
45419af5a38SHeinrich Kuhn 
45519af5a38SHeinrich Kuhn 			if (op == NFP_BRIDGE_OP_IOCTL)
45619af5a38SHeinrich Kuhn 				nfp_cpp_bridge_serve_ioctl(datafd, cpp);
45719af5a38SHeinrich Kuhn 
45819af5a38SHeinrich Kuhn 			if (op == 0)
45919af5a38SHeinrich Kuhn 				break;
46019af5a38SHeinrich Kuhn 		}
46119af5a38SHeinrich Kuhn 		close(datafd);
46219af5a38SHeinrich Kuhn 	}
46319af5a38SHeinrich Kuhn 	close(sockfd);
46419af5a38SHeinrich Kuhn 
46519af5a38SHeinrich Kuhn 	return 0;
46619af5a38SHeinrich Kuhn }
467