xref: /dpdk/drivers/net/nfp/nfpcore/nfp_sync.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
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