]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/drivers/net/nfp/nfpcore/nfp_resource.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / spdk / dpdk / drivers / net / nfp / nfpcore / nfp_resource.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
3 * All rights reserved.
4 */
5
6 #include <stdio.h>
7 #include <time.h>
8 #include <endian.h>
9
10 #include <rte_string_fns.h>
11
12 #include "nfp_cpp.h"
13 #include "nfp6000/nfp6000.h"
14 #include "nfp_resource.h"
15 #include "nfp_crc.h"
16
17 #define NFP_RESOURCE_TBL_TARGET NFP_CPP_TARGET_MU
18 #define NFP_RESOURCE_TBL_BASE 0x8100000000ULL
19
20 /* NFP Resource Table self-identifier */
21 #define NFP_RESOURCE_TBL_NAME "nfp.res"
22 #define NFP_RESOURCE_TBL_KEY 0x00000000 /* Special key for entry 0 */
23
24 #define NFP_RESOURCE_ENTRY_NAME_SZ 8
25
26 /*
27 * struct nfp_resource_entry - Resource table entry
28 * @owner: NFP CPP Lock, interface owner
29 * @key: NFP CPP Lock, posix_crc32(name, 8)
30 * @region: Memory region descriptor
31 * @name: ASCII, zero padded name
32 * @reserved
33 * @cpp_action: CPP Action
34 * @cpp_token: CPP Token
35 * @cpp_target: CPP Target ID
36 * @page_offset: 256-byte page offset into target's CPP address
37 * @page_size: size, in 256-byte pages
38 */
39 struct nfp_resource_entry {
40 struct nfp_resource_entry_mutex {
41 uint32_t owner;
42 uint32_t key;
43 } mutex;
44 struct nfp_resource_entry_region {
45 uint8_t name[NFP_RESOURCE_ENTRY_NAME_SZ];
46 uint8_t reserved[5];
47 uint8_t cpp_action;
48 uint8_t cpp_token;
49 uint8_t cpp_target;
50 uint32_t page_offset;
51 uint32_t page_size;
52 } region;
53 };
54
55 #define NFP_RESOURCE_TBL_SIZE 4096
56 #define NFP_RESOURCE_TBL_ENTRIES (int)(NFP_RESOURCE_TBL_SIZE / \
57 sizeof(struct nfp_resource_entry))
58
59 struct nfp_resource {
60 char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1];
61 uint32_t cpp_id;
62 uint64_t addr;
63 uint64_t size;
64 struct nfp_cpp_mutex *mutex;
65 };
66
67 static int
68 nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
69 {
70 char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ + 2];
71 struct nfp_resource_entry entry;
72 uint32_t cpp_id, key;
73 int ret, i;
74
75 cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0); /* Atomic read */
76
77 memset(name_pad, 0, sizeof(name_pad));
78 strlcpy(name_pad, res->name, sizeof(name_pad));
79
80 /* Search for a matching entry */
81 if (!memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8)) {
82 printf("Grabbing device lock not supported\n");
83 return -EOPNOTSUPP;
84 }
85 key = nfp_crc32_posix(name_pad, NFP_RESOURCE_ENTRY_NAME_SZ);
86
87 for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
88 uint64_t addr = NFP_RESOURCE_TBL_BASE +
89 sizeof(struct nfp_resource_entry) * i;
90
91 ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry));
92 if (ret != sizeof(entry))
93 return -EIO;
94
95 if (entry.mutex.key != key)
96 continue;
97
98 /* Found key! */
99 res->mutex =
100 nfp_cpp_mutex_alloc(cpp,
101 NFP_RESOURCE_TBL_TARGET, addr, key);
102 res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
103 entry.region.cpp_action,
104 entry.region.cpp_token);
105 res->addr = ((uint64_t)entry.region.page_offset) << 8;
106 res->size = (uint64_t)entry.region.page_size << 8;
107 return 0;
108 }
109
110 return -ENOENT;
111 }
112
113 static int
114 nfp_resource_try_acquire(struct nfp_cpp *cpp, struct nfp_resource *res,
115 struct nfp_cpp_mutex *dev_mutex)
116 {
117 int err;
118
119 if (nfp_cpp_mutex_lock(dev_mutex))
120 return -EINVAL;
121
122 err = nfp_cpp_resource_find(cpp, res);
123 if (err)
124 goto err_unlock_dev;
125
126 err = nfp_cpp_mutex_trylock(res->mutex);
127 if (err)
128 goto err_res_mutex_free;
129
130 nfp_cpp_mutex_unlock(dev_mutex);
131
132 return 0;
133
134 err_res_mutex_free:
135 nfp_cpp_mutex_free(res->mutex);
136 err_unlock_dev:
137 nfp_cpp_mutex_unlock(dev_mutex);
138
139 return err;
140 }
141
142 /*
143 * nfp_resource_acquire() - Acquire a resource handle
144 * @cpp: NFP CPP handle
145 * @name: Name of the resource
146 *
147 * NOTE: This function locks the acquired resource
148 *
149 * Return: NFP Resource handle, or ERR_PTR()
150 */
151 struct nfp_resource *
152 nfp_resource_acquire(struct nfp_cpp *cpp, const char *name)
153 {
154 struct nfp_cpp_mutex *dev_mutex;
155 struct nfp_resource *res;
156 int err;
157 struct timespec wait;
158 int count;
159
160 res = malloc(sizeof(*res));
161 if (!res)
162 return NULL;
163
164 memset(res, 0, sizeof(*res));
165
166 strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ);
167
168 dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
169 NFP_RESOURCE_TBL_BASE,
170 NFP_RESOURCE_TBL_KEY);
171 if (!dev_mutex) {
172 free(res);
173 return NULL;
174 }
175
176 wait.tv_sec = 0;
177 wait.tv_nsec = 1000000;
178 count = 0;
179
180 for (;;) {
181 err = nfp_resource_try_acquire(cpp, res, dev_mutex);
182 if (!err)
183 break;
184 if (err != -EBUSY)
185 goto err_free;
186
187 if (count++ > 1000) {
188 printf("Error: resource %s timed out\n", name);
189 err = -EBUSY;
190 goto err_free;
191 }
192
193 nanosleep(&wait, NULL);
194 }
195
196 nfp_cpp_mutex_free(dev_mutex);
197
198 return res;
199
200 err_free:
201 nfp_cpp_mutex_free(dev_mutex);
202 free(res);
203 return NULL;
204 }
205
206 /*
207 * nfp_resource_release() - Release a NFP Resource handle
208 * @res: NFP Resource handle
209 *
210 * NOTE: This function implictly unlocks the resource handle
211 */
212 void
213 nfp_resource_release(struct nfp_resource *res)
214 {
215 nfp_cpp_mutex_unlock(res->mutex);
216 nfp_cpp_mutex_free(res->mutex);
217 free(res);
218 }
219
220 /*
221 * nfp_resource_cpp_id() - Return the cpp_id of a resource handle
222 * @res: NFP Resource handle
223 *
224 * Return: NFP CPP ID
225 */
226 uint32_t
227 nfp_resource_cpp_id(const struct nfp_resource *res)
228 {
229 return res->cpp_id;
230 }
231
232 /*
233 * nfp_resource_name() - Return the name of a resource handle
234 * @res: NFP Resource handle
235 *
236 * Return: const char pointer to the name of the resource
237 */
238 const char
239 *nfp_resource_name(const struct nfp_resource *res)
240 {
241 return res->name;
242 }
243
244 /*
245 * nfp_resource_address() - Return the address of a resource handle
246 * @res: NFP Resource handle
247 *
248 * Return: Address of the resource
249 */
250 uint64_t
251 nfp_resource_address(const struct nfp_resource *res)
252 {
253 return res->addr;
254 }
255
256 /*
257 * nfp_resource_size() - Return the size in bytes of a resource handle
258 * @res: NFP Resource handle
259 *
260 * Return: Size of the resource in bytes
261 */
262 uint64_t
263 nfp_resource_size(const struct nfp_resource *res)
264 {
265 return res->size;
266 }