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