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