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 83*bab0e6f4SChaoyong 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 92*bab0e6f4SChaoyong 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 101*bab0e6f4SChaoyong 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); 16419af5a38SHeinrich Kuhn if (!area) { 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); 26419af5a38SHeinrich Kuhn if (!area) { 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; 379*bab0e6f4SChaoyong He struct nfp_cpp *cpp; 380*bab0e6f4SChaoyong He struct nfp_pf_dev *pf_dev; 38119af5a38SHeinrich Kuhn int sockfd, datafd, op, ret; 38219af5a38SHeinrich Kuhn 38319af5a38SHeinrich Kuhn unlink("/tmp/nfp_cpp"); 38419af5a38SHeinrich Kuhn sockfd = socket(AF_UNIX, SOCK_STREAM, 0); 38519af5a38SHeinrich Kuhn if (sockfd < 0) { 38619af5a38SHeinrich Kuhn RTE_LOG(ERR, PMD, "%s: socket creation error. Service failed\n", 38719af5a38SHeinrich Kuhn __func__); 38819af5a38SHeinrich Kuhn return -EIO; 38919af5a38SHeinrich Kuhn } 39019af5a38SHeinrich Kuhn 39119af5a38SHeinrich Kuhn memset(&address, 0, sizeof(struct sockaddr)); 39219af5a38SHeinrich Kuhn 39319af5a38SHeinrich Kuhn address.sa_family = AF_UNIX; 39419af5a38SHeinrich Kuhn strcpy(address.sa_data, "/tmp/nfp_cpp"); 39519af5a38SHeinrich Kuhn 39619af5a38SHeinrich Kuhn ret = bind(sockfd, (const struct sockaddr *)&address, 39719af5a38SHeinrich Kuhn sizeof(struct sockaddr)); 39819af5a38SHeinrich Kuhn if (ret < 0) { 39919af5a38SHeinrich Kuhn RTE_LOG(ERR, PMD, "%s: bind error (%d). Service failed\n", 40019af5a38SHeinrich Kuhn __func__, errno); 40119af5a38SHeinrich Kuhn close(sockfd); 40219af5a38SHeinrich Kuhn return ret; 40319af5a38SHeinrich Kuhn } 40419af5a38SHeinrich Kuhn 40519af5a38SHeinrich Kuhn ret = listen(sockfd, 20); 40619af5a38SHeinrich Kuhn if (ret < 0) { 40719af5a38SHeinrich Kuhn RTE_LOG(ERR, PMD, "%s: listen error(%d). Service failed\n", 40819af5a38SHeinrich Kuhn __func__, errno); 40919af5a38SHeinrich Kuhn close(sockfd); 41019af5a38SHeinrich Kuhn return ret; 41119af5a38SHeinrich Kuhn } 41219af5a38SHeinrich Kuhn 413*bab0e6f4SChaoyong He pf_dev = args; 414*bab0e6f4SChaoyong He cpp = pf_dev->cpp; 415*bab0e6f4SChaoyong He while (rte_service_runstate_get(pf_dev->cpp_bridge_id) != 0) { 41619af5a38SHeinrich Kuhn datafd = accept(sockfd, NULL, NULL); 41719af5a38SHeinrich Kuhn if (datafd < 0) { 41819af5a38SHeinrich Kuhn RTE_LOG(ERR, PMD, "%s: accept call error (%d)\n", 41919af5a38SHeinrich Kuhn __func__, errno); 42019af5a38SHeinrich Kuhn RTE_LOG(ERR, PMD, "%s: service failed\n", __func__); 42119af5a38SHeinrich Kuhn close(sockfd); 42219af5a38SHeinrich Kuhn return -EIO; 42319af5a38SHeinrich Kuhn } 42419af5a38SHeinrich Kuhn 42519af5a38SHeinrich Kuhn while (1) { 42619af5a38SHeinrich Kuhn ret = recv(datafd, &op, 4, 0); 42719af5a38SHeinrich Kuhn if (ret <= 0) { 42819af5a38SHeinrich Kuhn PMD_CPP_LOG(DEBUG, "%s: socket close\n", 42919af5a38SHeinrich Kuhn __func__); 43019af5a38SHeinrich Kuhn break; 43119af5a38SHeinrich Kuhn } 43219af5a38SHeinrich Kuhn 43319af5a38SHeinrich Kuhn PMD_CPP_LOG(DEBUG, "%s: getting op %u\n", __func__, op); 43419af5a38SHeinrich Kuhn 43519af5a38SHeinrich Kuhn if (op == NFP_BRIDGE_OP_READ) 43619af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_read(datafd, cpp); 43719af5a38SHeinrich Kuhn 43819af5a38SHeinrich Kuhn if (op == NFP_BRIDGE_OP_WRITE) 43919af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_write(datafd, cpp); 44019af5a38SHeinrich Kuhn 44119af5a38SHeinrich Kuhn if (op == NFP_BRIDGE_OP_IOCTL) 44219af5a38SHeinrich Kuhn nfp_cpp_bridge_serve_ioctl(datafd, cpp); 44319af5a38SHeinrich Kuhn 44419af5a38SHeinrich Kuhn if (op == 0) 44519af5a38SHeinrich Kuhn break; 44619af5a38SHeinrich Kuhn } 44719af5a38SHeinrich Kuhn close(datafd); 44819af5a38SHeinrich Kuhn } 44919af5a38SHeinrich Kuhn close(sockfd); 45019af5a38SHeinrich Kuhn 45119af5a38SHeinrich Kuhn return 0; 45219af5a38SHeinrich Kuhn } 45319af5a38SHeinrich Kuhn /* 45419af5a38SHeinrich Kuhn * Local variables: 45519af5a38SHeinrich Kuhn * c-file-style: "Linux" 45619af5a38SHeinrich Kuhn * indent-tabs-mode: t 45719af5a38SHeinrich Kuhn * End: 45819af5a38SHeinrich Kuhn */ 459