16b4273a0SLong Wu /* SPDX-License-Identifier: BSD-3-Clause 26b4273a0SLong Wu * Copyright (c) 2024 Corigine, Inc. 36b4273a0SLong Wu * All rights reserved. 46b4273a0SLong Wu */ 56b4273a0SLong Wu 66b4273a0SLong Wu #include "nfp_sync.h" 76b4273a0SLong Wu 86b4273a0SLong Wu #include <rte_dev.h> 96b4273a0SLong Wu #include <rte_malloc.h> 106b4273a0SLong Wu #include <rte_memzone.h> 116b4273a0SLong Wu #include <rte_spinlock.h> 12511d4a76SChaoyong He #include <rte_string_fns.h> 136b4273a0SLong Wu 146b4273a0SLong Wu #include "nfp_logs.h" 156b4273a0SLong Wu 166b4273a0SLong Wu #define NFP_SYNC_ELEMENT_MAX 8 176b4273a0SLong Wu #define NFP_SYNC_PCI_MAX 32 186b4273a0SLong Wu 196b4273a0SLong Wu struct nfp_sync_element { 206b4273a0SLong Wu uint16_t count; 216b4273a0SLong Wu /** Element ID, use ASCII - SYN<> */ 226b4273a0SLong Wu uint32_t magic; 236b4273a0SLong Wu void *handle; 246b4273a0SLong Wu }; 256b4273a0SLong Wu 266b4273a0SLong Wu struct nfp_sync_common { 276b4273a0SLong Wu char pci_name[PCI_PRI_STR_SIZE + 1]; 286b4273a0SLong Wu uint16_t avail; 296b4273a0SLong Wu struct nfp_sync_element element[NFP_SYNC_ELEMENT_MAX]; 306b4273a0SLong Wu }; 316b4273a0SLong Wu 326b4273a0SLong Wu struct nfp_sync { 336b4273a0SLong Wu rte_spinlock_t spinlock; 346b4273a0SLong Wu 356b4273a0SLong Wu uint16_t alloc_count; 366b4273a0SLong Wu 376b4273a0SLong Wu struct nfp_sync_common process; 386b4273a0SLong Wu 396b4273a0SLong Wu struct nfp_sync_common pci[NFP_SYNC_PCI_MAX]; 406b4273a0SLong Wu 416b4273a0SLong Wu const struct rte_memzone *mz; 426b4273a0SLong Wu }; 436b4273a0SLong Wu 446b4273a0SLong Wu struct nfp_sync * 456b4273a0SLong Wu nfp_sync_alloc(void) 466b4273a0SLong Wu { 476b4273a0SLong Wu uint16_t i; 486b4273a0SLong Wu struct nfp_sync *sync; 496b4273a0SLong Wu const struct rte_memzone *mz; 506b4273a0SLong Wu 516b4273a0SLong Wu mz = rte_memzone_lookup("nfp_sync"); 526b4273a0SLong Wu if (mz != NULL) { 536b4273a0SLong Wu sync = mz->addr; 546b4273a0SLong Wu sync->alloc_count++; 556b4273a0SLong Wu 566b4273a0SLong Wu return sync; 576b4273a0SLong Wu } 586b4273a0SLong Wu 596b4273a0SLong Wu mz = rte_memzone_reserve("nfp_sync", sizeof(*sync), SOCKET_ID_ANY, 606b4273a0SLong Wu RTE_MEMZONE_SIZE_HINT_ONLY); 616b4273a0SLong Wu if (mz == NULL) 626b4273a0SLong Wu return NULL; 636b4273a0SLong Wu 646b4273a0SLong Wu sync = mz->addr; 656b4273a0SLong Wu 666b4273a0SLong Wu memset(sync, 0, sizeof(*sync)); 676b4273a0SLong Wu 686b4273a0SLong Wu rte_spinlock_init(&sync->spinlock); 696b4273a0SLong Wu sync->alloc_count = 1; 706b4273a0SLong Wu sync->mz = mz; 716b4273a0SLong Wu 726b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) 736b4273a0SLong Wu sync->pci[i].avail = NFP_SYNC_ELEMENT_MAX; 746b4273a0SLong Wu 756b4273a0SLong Wu sync->process.avail = NFP_SYNC_ELEMENT_MAX; 766b4273a0SLong Wu 776b4273a0SLong Wu return sync; 786b4273a0SLong Wu } 796b4273a0SLong Wu 806b4273a0SLong Wu void 816b4273a0SLong Wu nfp_sync_free(struct nfp_sync *sync) 826b4273a0SLong Wu { 836b4273a0SLong Wu uint16_t i; 846b4273a0SLong Wu 856b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 866b4273a0SLong Wu 876b4273a0SLong Wu sync->alloc_count--; 886b4273a0SLong Wu if (sync->alloc_count != 0) { 896b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 906b4273a0SLong Wu return; 916b4273a0SLong Wu } 926b4273a0SLong Wu 936b4273a0SLong Wu if (sync->process.avail != NFP_SYNC_ELEMENT_MAX) 94*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Sync process handle residue."); 956b4273a0SLong Wu 966b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) { 976b4273a0SLong Wu if (sync->pci[i].avail != NFP_SYNC_ELEMENT_MAX) 98*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Sync %s pci handle residue.", 996b4273a0SLong Wu sync->pci[i].pci_name); 1006b4273a0SLong Wu } 1016b4273a0SLong Wu 1026b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 1036b4273a0SLong Wu 1046b4273a0SLong Wu rte_memzone_free(sync->mz); 1056b4273a0SLong Wu } 1066b4273a0SLong Wu 1076b4273a0SLong Wu static void * 1086b4273a0SLong Wu nfp_sync_element_alloc(struct nfp_sync_element *element, 1096b4273a0SLong Wu uint32_t magic, 1106b4273a0SLong Wu uint32_t size) 1116b4273a0SLong Wu { 1126b4273a0SLong Wu void *handle; 1136b4273a0SLong Wu 1146b4273a0SLong Wu handle = rte_zmalloc(NULL, size, 0); 1156b4273a0SLong Wu if (handle == NULL) 1166b4273a0SLong Wu return NULL; 1176b4273a0SLong Wu 1186b4273a0SLong Wu element->handle = handle; 1196b4273a0SLong Wu element->count = 1; 1206b4273a0SLong Wu element->magic = magic; 1216b4273a0SLong Wu 1226b4273a0SLong Wu return handle; 1236b4273a0SLong Wu } 1246b4273a0SLong Wu 1256b4273a0SLong Wu static void 1266b4273a0SLong Wu nfp_sync_element_free(struct nfp_sync_element *element, 1276b4273a0SLong Wu void *handle) 1286b4273a0SLong Wu { 1296b4273a0SLong Wu element->count--; 1306b4273a0SLong Wu if (element->count != 0) 1316b4273a0SLong Wu return; 1326b4273a0SLong Wu 1336b4273a0SLong Wu rte_free(handle); 1346b4273a0SLong Wu element->handle = NULL; 1356b4273a0SLong Wu element->magic = 0; 1366b4273a0SLong Wu } 1376b4273a0SLong Wu 1386b4273a0SLong Wu static void * 1396b4273a0SLong Wu nfp_sync_common_handle_alloc(struct nfp_sync_common *common, 1406b4273a0SLong Wu uint32_t magic, 1416b4273a0SLong Wu uint32_t size) 1426b4273a0SLong Wu { 1436b4273a0SLong Wu uint16_t i; 1446b4273a0SLong Wu void *handle = NULL; 1456b4273a0SLong Wu uint16_t avail_slot = NFP_SYNC_ELEMENT_MAX; 1466b4273a0SLong Wu 1476b4273a0SLong Wu for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) { 1486b4273a0SLong Wu if (common->element[i].magic != magic) 1496b4273a0SLong Wu continue; 1506b4273a0SLong Wu 1516b4273a0SLong Wu common->element[i].count++; 1526b4273a0SLong Wu 1536b4273a0SLong Wu return common->element[i].handle; 1546b4273a0SLong Wu } 1556b4273a0SLong Wu 1566b4273a0SLong Wu if (common->avail == 0) 1576b4273a0SLong Wu return NULL; 1586b4273a0SLong Wu 1596b4273a0SLong Wu for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) { 1606b4273a0SLong Wu if (common->element[i].magic == 0) { 1616b4273a0SLong Wu avail_slot = i; 1626b4273a0SLong Wu break; 1636b4273a0SLong Wu } 1646b4273a0SLong Wu } 1656b4273a0SLong Wu 1666b4273a0SLong Wu handle = nfp_sync_element_alloc(&common->element[avail_slot], magic, size); 1676b4273a0SLong Wu if (handle == NULL) 1686b4273a0SLong Wu return NULL; 1696b4273a0SLong Wu 1706b4273a0SLong Wu common->avail--; 1716b4273a0SLong Wu 1726b4273a0SLong Wu return handle; 1736b4273a0SLong Wu } 1746b4273a0SLong Wu 1756b4273a0SLong Wu static void 1766b4273a0SLong Wu nfp_sync_common_handle_free(struct nfp_sync_common *common, 1776b4273a0SLong Wu void *handle) 1786b4273a0SLong Wu { 1796b4273a0SLong Wu uint16_t i; 1806b4273a0SLong Wu 1816b4273a0SLong Wu if (common->avail == NFP_SYNC_ELEMENT_MAX) 1826b4273a0SLong Wu return; 1836b4273a0SLong Wu 1846b4273a0SLong Wu for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) { 1856b4273a0SLong Wu if (common->element[i].handle == handle) 1866b4273a0SLong Wu break; 1876b4273a0SLong Wu } 1886b4273a0SLong Wu 1896b4273a0SLong Wu if (i == NFP_SYNC_ELEMENT_MAX) 1906b4273a0SLong Wu return; 1916b4273a0SLong Wu 1926b4273a0SLong Wu nfp_sync_element_free(&common->element[i], handle); 1936b4273a0SLong Wu 1946b4273a0SLong Wu if (common->element[i].count == 0) 1956b4273a0SLong Wu common->avail++; 1966b4273a0SLong Wu } 1976b4273a0SLong Wu 1986b4273a0SLong Wu static void * 1996b4273a0SLong Wu nfp_sync_process_inner_handle_alloc(struct nfp_sync *sync, 2006b4273a0SLong Wu uint32_t magic, 2016b4273a0SLong Wu uint32_t size) 2026b4273a0SLong Wu { 2036b4273a0SLong Wu void *handle = NULL; 2046b4273a0SLong Wu 2056b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 2066b4273a0SLong Wu 2076b4273a0SLong Wu handle = nfp_sync_common_handle_alloc(&sync->process, magic, size); 2086b4273a0SLong Wu if (handle == NULL) 209*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "Process handle alloc failed."); 2106b4273a0SLong Wu 2116b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 2126b4273a0SLong Wu 2136b4273a0SLong Wu return handle; 2146b4273a0SLong Wu } 2156b4273a0SLong Wu 2166b4273a0SLong Wu static void 2176b4273a0SLong Wu nfp_sync_process_inner_handle_free(struct nfp_sync *sync, 2186b4273a0SLong Wu void *handle) 2196b4273a0SLong Wu { 2206b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 2216b4273a0SLong Wu 2226b4273a0SLong Wu nfp_sync_common_handle_free(&sync->process, handle); 2236b4273a0SLong Wu 2246b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 2256b4273a0SLong Wu } 2266b4273a0SLong Wu 2276b4273a0SLong Wu static uint16_t 2286b4273a0SLong Wu nfp_sync_process_handle_count_get(struct nfp_sync *sync, 2296b4273a0SLong Wu void *handle) 2306b4273a0SLong Wu { 2316b4273a0SLong Wu uint16_t i; 2326b4273a0SLong Wu uint16_t count = 0; 2336b4273a0SLong Wu 2346b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 2356b4273a0SLong Wu 2366b4273a0SLong Wu for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) { 2376b4273a0SLong Wu if (sync->process.element[i].handle == handle) { 2386b4273a0SLong Wu count = sync->process.element[i].count; 2396b4273a0SLong Wu break; 2406b4273a0SLong Wu } 2416b4273a0SLong Wu } 2426b4273a0SLong Wu 2436b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 2446b4273a0SLong Wu 2456b4273a0SLong Wu return count; 2466b4273a0SLong Wu } 2476b4273a0SLong Wu 2486b4273a0SLong Wu static void * 2496b4273a0SLong Wu nfp_sync_pci_inner_handle_alloc(struct nfp_sync *sync, 2506b4273a0SLong Wu const char *pci_name, 2516b4273a0SLong Wu uint32_t magic, 2526b4273a0SLong Wu uint32_t size) 2536b4273a0SLong Wu { 2546b4273a0SLong Wu uint16_t i; 2556b4273a0SLong Wu void *handle = NULL; 2566b4273a0SLong Wu uint16_t pci_avail_id = NFP_SYNC_PCI_MAX; 2576b4273a0SLong Wu 2586b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 2596b4273a0SLong Wu 2606b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) { 2616b4273a0SLong Wu if (strcmp(pci_name, sync->pci[i].pci_name) == 0) { 2626b4273a0SLong Wu pci_avail_id = i; 2636b4273a0SLong Wu goto common_alloc; 2646b4273a0SLong Wu } 2656b4273a0SLong Wu } 2666b4273a0SLong Wu 2676b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) { 2686b4273a0SLong Wu if (strlen(sync->pci[i].pci_name) == 0) { 2696b4273a0SLong Wu pci_avail_id = i; 270511d4a76SChaoyong He rte_strlcpy(sync->pci[pci_avail_id].pci_name, pci_name, PCI_PRI_STR_SIZE); 2716b4273a0SLong Wu goto common_alloc; 2726b4273a0SLong Wu } 2736b4273a0SLong Wu } 2746b4273a0SLong Wu 2756b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 2766b4273a0SLong Wu 2776b4273a0SLong Wu return NULL; 2786b4273a0SLong Wu 2796b4273a0SLong Wu common_alloc: 2806b4273a0SLong Wu handle = nfp_sync_common_handle_alloc(&sync->pci[pci_avail_id], 2816b4273a0SLong Wu magic, size); 2826b4273a0SLong Wu if (handle == NULL) 283*b6de4353SZerun Fu PMD_DRV_LOG(ERR, "PCI handle alloc failed."); 2846b4273a0SLong Wu 2856b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 2866b4273a0SLong Wu 2876b4273a0SLong Wu return handle; 2886b4273a0SLong Wu } 2896b4273a0SLong Wu 2906b4273a0SLong Wu static void 2916b4273a0SLong Wu nfp_sync_pci_inner_handle_free(struct nfp_sync *sync, 2926b4273a0SLong Wu const char *pci_name, 2936b4273a0SLong Wu void *handle) 2946b4273a0SLong Wu { 2956b4273a0SLong Wu uint16_t i; 2966b4273a0SLong Wu char *name_tmp; 2976b4273a0SLong Wu 2986b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 2996b4273a0SLong Wu 3006b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) { 3016b4273a0SLong Wu name_tmp = sync->pci[i].pci_name; 3026b4273a0SLong Wu if (strlen(name_tmp) != 0 && strcmp(pci_name, name_tmp) == 0) { 3036b4273a0SLong Wu nfp_sync_common_handle_free(&sync->pci[i], handle); 3046b4273a0SLong Wu if (sync->pci[i].avail == NFP_SYNC_ELEMENT_MAX) 3056b4273a0SLong Wu name_tmp[0] = 0; 3066b4273a0SLong Wu break; 3076b4273a0SLong Wu } 3086b4273a0SLong Wu } 3096b4273a0SLong Wu 3106b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 3116b4273a0SLong Wu } 3126b4273a0SLong Wu 3136b4273a0SLong Wu static uint16_t 3146b4273a0SLong Wu nfp_sync_pci_handle_count_get(struct nfp_sync *sync, 3156b4273a0SLong Wu const char *pci_name, 3166b4273a0SLong Wu void *handle) 3176b4273a0SLong Wu { 3186b4273a0SLong Wu uint16_t i; 3196b4273a0SLong Wu uint16_t count = 0; 3206b4273a0SLong Wu struct nfp_sync_common *pci_common; 3216b4273a0SLong Wu 3226b4273a0SLong Wu rte_spinlock_lock(&sync->spinlock); 3236b4273a0SLong Wu 3246b4273a0SLong Wu for (i = 0; i < NFP_SYNC_PCI_MAX; i++) { 3256b4273a0SLong Wu if (strcmp(sync->pci[i].pci_name, pci_name) == 0) 3266b4273a0SLong Wu break; 3276b4273a0SLong Wu } 3286b4273a0SLong Wu 3296b4273a0SLong Wu if (i == NFP_SYNC_PCI_MAX) { 3306b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 3316b4273a0SLong Wu return 0; 3326b4273a0SLong Wu } 3336b4273a0SLong Wu 3346b4273a0SLong Wu pci_common = &sync->pci[i]; 3356b4273a0SLong Wu 3366b4273a0SLong Wu for (i = 0; i < NFP_SYNC_ELEMENT_MAX; i++) { 3376b4273a0SLong Wu if (pci_common->element[i].handle == handle) { 3386b4273a0SLong Wu count = pci_common->element[i].count; 3396b4273a0SLong Wu break; 3406b4273a0SLong Wu } 3416b4273a0SLong Wu } 3426b4273a0SLong Wu 3436b4273a0SLong Wu rte_spinlock_unlock(&sync->spinlock); 3446b4273a0SLong Wu 3456b4273a0SLong Wu return count; 3466b4273a0SLong Wu } 3476b4273a0SLong Wu 3486b4273a0SLong Wu void * 3496b4273a0SLong Wu nfp_sync_handle_alloc(struct nfp_sync *sync, 3506b4273a0SLong Wu struct rte_pci_device *pci_dev, 3516b4273a0SLong Wu uint32_t magic, 3526b4273a0SLong Wu uint32_t size) 3536b4273a0SLong Wu { 3546b4273a0SLong Wu if (pci_dev == NULL) 3556b4273a0SLong Wu return nfp_sync_process_inner_handle_alloc(sync, magic, size); 3566b4273a0SLong Wu 3576b4273a0SLong Wu return nfp_sync_pci_inner_handle_alloc(sync, pci_dev->device.name, 3586b4273a0SLong Wu magic, size); 3596b4273a0SLong Wu } 3606b4273a0SLong Wu 3616b4273a0SLong Wu void 3626b4273a0SLong Wu nfp_sync_handle_free(struct nfp_sync *sync, 3636b4273a0SLong Wu struct rte_pci_device *pci_dev, 3646b4273a0SLong Wu void *handle) 3656b4273a0SLong Wu { 3666b4273a0SLong Wu if (pci_dev == NULL) { 3676b4273a0SLong Wu nfp_sync_process_inner_handle_free(sync, handle); 3686b4273a0SLong Wu return; 3696b4273a0SLong Wu } 3706b4273a0SLong Wu 3716b4273a0SLong Wu nfp_sync_pci_inner_handle_free(sync, pci_dev->device.name, handle); 3726b4273a0SLong Wu } 3736b4273a0SLong Wu 3746b4273a0SLong Wu uint16_t 3756b4273a0SLong Wu nfp_sync_handle_count_get(struct nfp_sync *sync, 3766b4273a0SLong Wu struct rte_pci_device *pci_dev, 3776b4273a0SLong Wu void *handle) 3786b4273a0SLong Wu { 3796b4273a0SLong Wu if (pci_dev == NULL) 3806b4273a0SLong Wu return nfp_sync_process_handle_count_get(sync, handle); 3816b4273a0SLong Wu 3826b4273a0SLong Wu return nfp_sync_pci_handle_count_get(sync, pci_dev->device.name, handle); 3836b4273a0SLong Wu } 384