xref: /dpdk/drivers/net/nfp/nfpcore/nfp_resource.c (revision b6de43530dfa30cbf6b70857e3835099701063d4)
1c7e9729dSAlejandro Lucero /* SPDX-License-Identifier: BSD-3-Clause
2c7e9729dSAlejandro Lucero  * Copyright(c) 2018 Netronome Systems, Inc.
3c7e9729dSAlejandro Lucero  * All rights reserved.
4c7e9729dSAlejandro Lucero  */
5c7e9729dSAlejandro Lucero 
602236d46SChaoyong He #include "nfp_resource.h"
7c7e9729dSAlejandro Lucero 
802236d46SChaoyong He #include "nfp_crc.h"
952d810dcSJames Hershaw #include "nfp_logs.h"
104b6c8db9SChaoyong He #include "nfp_mutex.h"
11055ccb33SChaoyong He #include "nfp_target.h"
12c7e9729dSAlejandro Lucero 
13c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_TARGET         NFP_CPP_TARGET_MU
14c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_BASE           0x8100000000ULL
15c7e9729dSAlejandro Lucero 
16c7e9729dSAlejandro Lucero /* NFP Resource Table self-identifier */
17c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_NAME           "nfp.res"
18c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_KEY            0x00000000 /* Special key for entry 0 */
19c7e9729dSAlejandro Lucero 
20c7e9729dSAlejandro Lucero #define NFP_RESOURCE_ENTRY_NAME_SZ      8
21c7e9729dSAlejandro Lucero 
226d03aa61SChaoyong He /* Resource table entry */
23c7e9729dSAlejandro Lucero struct nfp_resource_entry {
24c7e9729dSAlejandro Lucero 	struct nfp_resource_entry_mutex {
256d03aa61SChaoyong He 		uint32_t owner;  /**< NFP CPP Lock, interface owner */
266d03aa61SChaoyong He 		uint32_t key;    /**< NFP CPP Lock, posix_crc32(name, 8) */
27c7e9729dSAlejandro Lucero 	} mutex;
286d03aa61SChaoyong He 	/* Memory region descriptor */
29c7e9729dSAlejandro Lucero 	struct nfp_resource_entry_region {
306d03aa61SChaoyong He 		/** ASCII, zero padded name */
31c7e9729dSAlejandro Lucero 		uint8_t  name[NFP_RESOURCE_ENTRY_NAME_SZ];
32c7e9729dSAlejandro Lucero 		uint8_t  reserved[5];
336d03aa61SChaoyong He 		uint8_t  cpp_action;  /**< CPP Action */
346d03aa61SChaoyong He 		uint8_t  cpp_token;   /**< CPP Token */
356d03aa61SChaoyong He 		uint8_t  cpp_target;  /**< CPP Target ID */
366d03aa61SChaoyong He 		/** 256-byte page offset into target's CPP address */
37c7e9729dSAlejandro Lucero 		uint32_t page_offset;
386d03aa61SChaoyong He 		uint32_t page_size;   /**< Size, in 256-byte pages */
39c7e9729dSAlejandro Lucero 	} region;
40c7e9729dSAlejandro Lucero };
41c7e9729dSAlejandro Lucero 
42c7e9729dSAlejandro Lucero #define NFP_RESOURCE_TBL_SIZE       4096
4302236d46SChaoyong He #define NFP_RESOURCE_TBL_ENTRIES    (NFP_RESOURCE_TBL_SIZE /        \
44c7e9729dSAlejandro Lucero 					sizeof(struct nfp_resource_entry))
45c7e9729dSAlejandro Lucero 
46c7e9729dSAlejandro Lucero struct nfp_resource {
47c7e9729dSAlejandro Lucero 	char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1];
48c7e9729dSAlejandro Lucero 	uint32_t cpp_id;
49c7e9729dSAlejandro Lucero 	uint64_t addr;
50c7e9729dSAlejandro Lucero 	uint64_t size;
51c7e9729dSAlejandro Lucero 	struct nfp_cpp_mutex *mutex;
52c7e9729dSAlejandro Lucero };
53c7e9729dSAlejandro Lucero 
54c7e9729dSAlejandro Lucero static int
55d108b9e9SChaoyong He nfp_cpp_resource_find(struct nfp_cpp *cpp,
56d108b9e9SChaoyong He 		struct nfp_resource *res)
57c7e9729dSAlejandro Lucero {
58610bf14bSChaoyong He 	int ret;
59610bf14bSChaoyong He 	uint32_t i;
60610bf14bSChaoyong He 	uint32_t key;
61610bf14bSChaoyong He 	uint32_t cpp_id;
62c7e9729dSAlejandro Lucero 	struct nfp_resource_entry entry;
63610bf14bSChaoyong He 	char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ + 2];
64c7e9729dSAlejandro Lucero 
65c7e9729dSAlejandro Lucero 	cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0);  /* Atomic read */
66c7e9729dSAlejandro Lucero 
6762280b78SAndy Green 	memset(name_pad, 0, sizeof(name_pad));
6862280b78SAndy Green 	strlcpy(name_pad, res->name, sizeof(name_pad));
69c7e9729dSAlejandro Lucero 
70c7e9729dSAlejandro Lucero 	/* Search for a matching entry */
71cbcbfd73SJames Hershaw 	if (memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8) == 0) {
72*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Grabbing device lock not supported.");
73c7e9729dSAlejandro Lucero 		return -EOPNOTSUPP;
74c7e9729dSAlejandro Lucero 	}
75f842b01aSChaoyong He 
7662280b78SAndy Green 	key = nfp_crc32_posix(name_pad, NFP_RESOURCE_ENTRY_NAME_SZ);
77c7e9729dSAlejandro Lucero 
78c7e9729dSAlejandro Lucero 	for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
79c7e9729dSAlejandro Lucero 		uint64_t addr = NFP_RESOURCE_TBL_BASE +
80c7e9729dSAlejandro Lucero 				sizeof(struct nfp_resource_entry) * i;
81c7e9729dSAlejandro Lucero 
82c7e9729dSAlejandro Lucero 		ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry));
83c7e9729dSAlejandro Lucero 		if (ret != sizeof(entry))
84c7e9729dSAlejandro Lucero 			return -EIO;
85c7e9729dSAlejandro Lucero 
86c7e9729dSAlejandro Lucero 		if (entry.mutex.key != key)
87c7e9729dSAlejandro Lucero 			continue;
88c7e9729dSAlejandro Lucero 
89c7e9729dSAlejandro Lucero 		/* Found key! */
90d108b9e9SChaoyong He 		res->mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
91d108b9e9SChaoyong He 				addr, key);
92c7e9729dSAlejandro Lucero 		res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
93c7e9729dSAlejandro Lucero 				entry.region.cpp_action,
94c7e9729dSAlejandro Lucero 				entry.region.cpp_token);
95c7e9729dSAlejandro Lucero 		res->addr = ((uint64_t)entry.region.page_offset) << 8;
96c7e9729dSAlejandro Lucero 		res->size = (uint64_t)entry.region.page_size << 8;
97f842b01aSChaoyong He 
98c7e9729dSAlejandro Lucero 		return 0;
99c7e9729dSAlejandro Lucero 	}
100c7e9729dSAlejandro Lucero 
101c7e9729dSAlejandro Lucero 	return -ENOENT;
102c7e9729dSAlejandro Lucero }
103c7e9729dSAlejandro Lucero 
104c7e9729dSAlejandro Lucero static int
105d108b9e9SChaoyong He nfp_resource_try_acquire(struct nfp_cpp *cpp,
106d108b9e9SChaoyong He 		struct nfp_resource *res,
107c7e9729dSAlejandro Lucero 		struct nfp_cpp_mutex *dev_mutex)
108c7e9729dSAlejandro Lucero {
109c7e9729dSAlejandro Lucero 	int err;
110c7e9729dSAlejandro Lucero 
111efa766e1SChaoyong He 	if (nfp_cpp_mutex_lock(dev_mutex) != 0) {
112*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex lock failed.");
113c7e9729dSAlejandro Lucero 		return -EINVAL;
114efa766e1SChaoyong He 	}
115c7e9729dSAlejandro Lucero 
116c7e9729dSAlejandro Lucero 	err = nfp_cpp_resource_find(cpp, res);
117efa766e1SChaoyong He 	if (err != 0) {
118*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RESOURCE - CPP resource find failed.");
119c7e9729dSAlejandro Lucero 		goto err_unlock_dev;
120efa766e1SChaoyong He 	}
121c7e9729dSAlejandro Lucero 
122c7e9729dSAlejandro Lucero 	err = nfp_cpp_mutex_trylock(res->mutex);
123efa766e1SChaoyong He 	if (err != 0) {
124*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex trylock failed.");
125c7e9729dSAlejandro Lucero 		goto err_res_mutex_free;
126efa766e1SChaoyong He 	}
127c7e9729dSAlejandro Lucero 
128c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_unlock(dev_mutex);
129c7e9729dSAlejandro Lucero 
130c7e9729dSAlejandro Lucero 	return 0;
131c7e9729dSAlejandro Lucero 
132c7e9729dSAlejandro Lucero err_res_mutex_free:
133c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_free(res->mutex);
134c7e9729dSAlejandro Lucero err_unlock_dev:
135c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_unlock(dev_mutex);
136c7e9729dSAlejandro Lucero 
137c7e9729dSAlejandro Lucero 	return err;
138c7e9729dSAlejandro Lucero }
139c7e9729dSAlejandro Lucero 
1406d03aa61SChaoyong He /**
1416d03aa61SChaoyong He  * Acquire a resource handle
142c7e9729dSAlejandro Lucero  *
1436d03aa61SChaoyong He  * Note: This function locks the acquired resource.
144c7e9729dSAlejandro Lucero  *
1456d03aa61SChaoyong He  * @param cpp
1466d03aa61SChaoyong He  *   NFP CPP handle
1476d03aa61SChaoyong He  * @param name
1486d03aa61SChaoyong He  *   Name of the resource
1496d03aa61SChaoyong He  *
1506d03aa61SChaoyong He  * @return
1516d03aa61SChaoyong He  *   NFP Resource handle, or NULL
152c7e9729dSAlejandro Lucero  */
153c7e9729dSAlejandro Lucero struct nfp_resource *
154d108b9e9SChaoyong He nfp_resource_acquire(struct nfp_cpp *cpp,
155d108b9e9SChaoyong He 		const char *name)
156c7e9729dSAlejandro Lucero {
157c7e9729dSAlejandro Lucero 	int err;
158610bf14bSChaoyong He 	uint16_t count = 0;
159c7e9729dSAlejandro Lucero 	struct timespec wait;
160610bf14bSChaoyong He 	struct nfp_resource *res;
161610bf14bSChaoyong He 	struct nfp_cpp_mutex *dev_mutex;
162c7e9729dSAlejandro Lucero 
163c7e9729dSAlejandro Lucero 	res = malloc(sizeof(*res));
164aa6b4a80SHuaxing Zhu 	if (res == NULL) {
165aa6b4a80SHuaxing Zhu 		PMD_DRV_LOG(ERR, "RESOURCE - Malloc NSP memory failed.");
166c7e9729dSAlejandro Lucero 		return NULL;
167aa6b4a80SHuaxing Zhu 	}
168c7e9729dSAlejandro Lucero 
169c7e9729dSAlejandro Lucero 	memset(res, 0, sizeof(*res));
170c7e9729dSAlejandro Lucero 
171c7e9729dSAlejandro Lucero 	strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ);
172c7e9729dSAlejandro Lucero 
173c7e9729dSAlejandro Lucero 	dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
174d108b9e9SChaoyong He 			NFP_RESOURCE_TBL_BASE, NFP_RESOURCE_TBL_KEY);
175cbcbfd73SJames Hershaw 	if (dev_mutex == NULL) {
176*b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RESOURCE - CPP mutex alloc failed.");
17702236d46SChaoyong He 		goto err_free;
178c7e9729dSAlejandro Lucero 	}
179c7e9729dSAlejandro Lucero 
180c7e9729dSAlejandro Lucero 	wait.tv_sec = 0;
1816d03aa61SChaoyong He 	wait.tv_nsec = 1000000;    /* 1ms */
182c7e9729dSAlejandro Lucero 
183c7e9729dSAlejandro Lucero 	for (;;) {
184c7e9729dSAlejandro Lucero 		err = nfp_resource_try_acquire(cpp, res, dev_mutex);
185cbcbfd73SJames Hershaw 		if (err == 0)
186c7e9729dSAlejandro Lucero 			break;
187efa766e1SChaoyong He 		if (err != -EBUSY) {
188*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "RESOURCE - try acquire failed.");
18902236d46SChaoyong He 			goto mutex_free;
190efa766e1SChaoyong He 		}
191c7e9729dSAlejandro Lucero 
1926d03aa61SChaoyong He 		if (count++ > 1000) {    /* 1ms * 1000 = 1s */
193*b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "Error: resource %s timed out.", name);
19402236d46SChaoyong He 			goto mutex_free;
195c7e9729dSAlejandro Lucero 		}
196c7e9729dSAlejandro Lucero 
197c7e9729dSAlejandro Lucero 		nanosleep(&wait, NULL);
198c7e9729dSAlejandro Lucero 	}
199c7e9729dSAlejandro Lucero 
200c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_free(dev_mutex);
201c7e9729dSAlejandro Lucero 
202c7e9729dSAlejandro Lucero 	return res;
203c7e9729dSAlejandro Lucero 
20402236d46SChaoyong He mutex_free:
205c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_free(dev_mutex);
20602236d46SChaoyong He err_free:
207c7e9729dSAlejandro Lucero 	free(res);
208c7e9729dSAlejandro Lucero 	return NULL;
209c7e9729dSAlejandro Lucero }
210c7e9729dSAlejandro Lucero 
2116d03aa61SChaoyong He /**
2126d03aa61SChaoyong He  * Release a NFP Resource handle
213c7e9729dSAlejandro Lucero  *
2146d03aa61SChaoyong He  * NOTE: This function implicitly unlocks the resource handle.
2156d03aa61SChaoyong He  *
2166d03aa61SChaoyong He  * @param res
2176d03aa61SChaoyong He  *   NFP Resource handle
218c7e9729dSAlejandro Lucero  */
219c7e9729dSAlejandro Lucero void
220c7e9729dSAlejandro Lucero nfp_resource_release(struct nfp_resource *res)
221c7e9729dSAlejandro Lucero {
222c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_unlock(res->mutex);
223c7e9729dSAlejandro Lucero 	nfp_cpp_mutex_free(res->mutex);
224c7e9729dSAlejandro Lucero 	free(res);
225c7e9729dSAlejandro Lucero }
226c7e9729dSAlejandro Lucero 
2276d03aa61SChaoyong He /**
2286d03aa61SChaoyong He  * Return the cpp_id of a resource handle
229c7e9729dSAlejandro Lucero  *
2306d03aa61SChaoyong He  * @param res
2316d03aa61SChaoyong He  *   NFP Resource handle
2326d03aa61SChaoyong He  *
2336d03aa61SChaoyong He  * @return
2346d03aa61SChaoyong He  *   NFP CPP ID
235c7e9729dSAlejandro Lucero  */
236c7e9729dSAlejandro Lucero uint32_t
237c7e9729dSAlejandro Lucero nfp_resource_cpp_id(const struct nfp_resource *res)
238c7e9729dSAlejandro Lucero {
239c7e9729dSAlejandro Lucero 	return res->cpp_id;
240c7e9729dSAlejandro Lucero }
241c7e9729dSAlejandro Lucero 
2426d03aa61SChaoyong He /**
2436d03aa61SChaoyong He  * Return the name of a resource handle
244c7e9729dSAlejandro Lucero  *
2456d03aa61SChaoyong He  * @param res
2466d03aa61SChaoyong He  *   NFP Resource handle
2476d03aa61SChaoyong He  *
2486d03aa61SChaoyong He  * @return
2496d03aa61SChaoyong He  *   Const char pointer to the name of the resource
250c7e9729dSAlejandro Lucero  */
251d108b9e9SChaoyong He const char *
252d108b9e9SChaoyong He nfp_resource_name(const struct nfp_resource *res)
253c7e9729dSAlejandro Lucero {
254c7e9729dSAlejandro Lucero 	return res->name;
255c7e9729dSAlejandro Lucero }
256c7e9729dSAlejandro Lucero 
2576d03aa61SChaoyong He /**
2586d03aa61SChaoyong He  * Return the address of a resource handle
259c7e9729dSAlejandro Lucero  *
2606d03aa61SChaoyong He  * @param res
2616d03aa61SChaoyong He  *   NFP Resource handle
2626d03aa61SChaoyong He  *
2636d03aa61SChaoyong He  * @return
2646d03aa61SChaoyong He  *   Address of the resource
265c7e9729dSAlejandro Lucero  */
266c7e9729dSAlejandro Lucero uint64_t
267c7e9729dSAlejandro Lucero nfp_resource_address(const struct nfp_resource *res)
268c7e9729dSAlejandro Lucero {
269c7e9729dSAlejandro Lucero 	return res->addr;
270c7e9729dSAlejandro Lucero }
271c7e9729dSAlejandro Lucero 
2726d03aa61SChaoyong He /**
2736d03aa61SChaoyong He  * Return the size in bytes of a resource handle
274c7e9729dSAlejandro Lucero  *
2756d03aa61SChaoyong He  * @param res
2766d03aa61SChaoyong He  *   NFP Resource handle
2776d03aa61SChaoyong He  *
2786d03aa61SChaoyong He  * @return
2796d03aa61SChaoyong He  *   Size of the resource in bytes
280c7e9729dSAlejandro Lucero  */
281c7e9729dSAlejandro Lucero uint64_t
282c7e9729dSAlejandro Lucero nfp_resource_size(const struct nfp_resource *res)
283c7e9729dSAlejandro Lucero {
284c7e9729dSAlejandro Lucero 	return res->size;
285c7e9729dSAlejandro Lucero }
286