This source file includes following definitions.
- nfp_cpp_resource_find
- nfp_resource_try_acquire
- nfp_resource_acquire
- nfp_resource_release
- nfp_resource_wait
- nfp_resource_cpp_id
- nfp_resource_name
- nfp_resource_address
- nfp_resource_size
- nfp_resource_table_init
1
2
3
4
5
6
7
8
9 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12
13 #include "crc32.h"
14 #include "nfp.h"
15 #include "nfp_cpp.h"
16 #include "nfp6000/nfp6000.h"
17
18 #define NFP_RESOURCE_TBL_TARGET NFP_CPP_TARGET_MU
19 #define NFP_RESOURCE_TBL_BASE 0x8100000000ULL
20
21
22 #define NFP_RESOURCE_TBL_NAME "nfp.res"
23 #define NFP_RESOURCE_TBL_KEY 0x00000000
24
25 #define NFP_RESOURCE_ENTRY_NAME_SZ 8
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 struct nfp_resource_entry {
42 struct nfp_resource_entry_mutex {
43 u32 owner;
44 u32 key;
45 } mutex;
46 struct nfp_resource_entry_region {
47 u8 name[NFP_RESOURCE_ENTRY_NAME_SZ];
48 u8 reserved[5];
49 u8 cpp_action;
50 u8 cpp_token;
51 u8 cpp_target;
52 u32 page_offset;
53 u32 page_size;
54 } region;
55 };
56
57 #define NFP_RESOURCE_TBL_SIZE 4096
58 #define NFP_RESOURCE_TBL_ENTRIES (NFP_RESOURCE_TBL_SIZE / \
59 sizeof(struct nfp_resource_entry))
60
61 struct nfp_resource {
62 char name[NFP_RESOURCE_ENTRY_NAME_SZ + 1];
63 u32 cpp_id;
64 u64 addr;
65 u64 size;
66 struct nfp_cpp_mutex *mutex;
67 };
68
69 static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
70 {
71 struct nfp_resource_entry entry;
72 u32 cpp_id, key;
73 int ret, i;
74
75 cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0);
76
77
78 if (!strcmp(res->name, NFP_RESOURCE_TBL_NAME)) {
79 nfp_err(cpp, "Grabbing device lock not supported\n");
80 return -EOPNOTSUPP;
81 }
82 key = crc32_posix(res->name, NFP_RESOURCE_ENTRY_NAME_SZ);
83
84 for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
85 u64 addr = NFP_RESOURCE_TBL_BASE +
86 sizeof(struct nfp_resource_entry) * i;
87
88 ret = nfp_cpp_read(cpp, cpp_id, addr, &entry, sizeof(entry));
89 if (ret != sizeof(entry))
90 return -EIO;
91
92 if (entry.mutex.key != key)
93 continue;
94
95
96 res->mutex =
97 nfp_cpp_mutex_alloc(cpp,
98 NFP_RESOURCE_TBL_TARGET, addr, key);
99 res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
100 entry.region.cpp_action,
101 entry.region.cpp_token);
102 res->addr = (u64)entry.region.page_offset << 8;
103 res->size = (u64)entry.region.page_size << 8;
104
105 return 0;
106 }
107
108 return -ENOENT;
109 }
110
111 static int
112 nfp_resource_try_acquire(struct nfp_cpp *cpp, struct nfp_resource *res,
113 struct nfp_cpp_mutex *dev_mutex)
114 {
115 int err;
116
117 if (nfp_cpp_mutex_lock(dev_mutex))
118 return -EINVAL;
119
120 err = nfp_cpp_resource_find(cpp, res);
121 if (err)
122 goto err_unlock_dev;
123
124 err = nfp_cpp_mutex_trylock(res->mutex);
125 if (err)
126 goto err_res_mutex_free;
127
128 nfp_cpp_mutex_unlock(dev_mutex);
129
130 return 0;
131
132 err_res_mutex_free:
133 nfp_cpp_mutex_free(res->mutex);
134 err_unlock_dev:
135 nfp_cpp_mutex_unlock(dev_mutex);
136
137 return err;
138 }
139
140
141
142
143
144
145
146
147
148
149 struct nfp_resource *
150 nfp_resource_acquire(struct nfp_cpp *cpp, const char *name)
151 {
152 unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ;
153 unsigned long err_at = jiffies + NFP_MUTEX_WAIT_ERROR * HZ;
154 struct nfp_cpp_mutex *dev_mutex;
155 struct nfp_resource *res;
156 int err;
157
158 res = kzalloc(sizeof(*res), GFP_KERNEL);
159 if (!res)
160 return ERR_PTR(-ENOMEM);
161
162 strncpy(res->name, name, NFP_RESOURCE_ENTRY_NAME_SZ);
163
164 dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
165 NFP_RESOURCE_TBL_BASE,
166 NFP_RESOURCE_TBL_KEY);
167 if (!dev_mutex) {
168 kfree(res);
169 return ERR_PTR(-ENOMEM);
170 }
171
172 for (;;) {
173 err = nfp_resource_try_acquire(cpp, res, dev_mutex);
174 if (!err)
175 break;
176 if (err != -EBUSY)
177 goto err_free;
178
179 err = msleep_interruptible(1);
180 if (err != 0) {
181 err = -ERESTARTSYS;
182 goto err_free;
183 }
184
185 if (time_is_before_eq_jiffies(warn_at)) {
186 warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ;
187 nfp_warn(cpp, "Warning: waiting for NFP resource %s\n",
188 name);
189 }
190 if (time_is_before_eq_jiffies(err_at)) {
191 nfp_err(cpp, "Error: resource %s timed out\n", name);
192 err = -EBUSY;
193 goto err_free;
194 }
195 }
196
197 nfp_cpp_mutex_free(dev_mutex);
198
199 return res;
200
201 err_free:
202 nfp_cpp_mutex_free(dev_mutex);
203 kfree(res);
204 return ERR_PTR(err);
205 }
206
207
208
209
210
211
212
213 void nfp_resource_release(struct nfp_resource *res)
214 {
215 nfp_cpp_mutex_unlock(res->mutex);
216 nfp_cpp_mutex_free(res->mutex);
217 kfree(res);
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231 int nfp_resource_wait(struct nfp_cpp *cpp, const char *name, unsigned int secs)
232 {
233 unsigned long warn_at = jiffies + NFP_MUTEX_WAIT_FIRST_WARN * HZ;
234 unsigned long err_at = jiffies + secs * HZ;
235 struct nfp_resource *res;
236
237 while (true) {
238 res = nfp_resource_acquire(cpp, name);
239 if (!IS_ERR(res)) {
240 nfp_resource_release(res);
241 return 0;
242 }
243
244 if (PTR_ERR(res) != -ENOENT) {
245 nfp_err(cpp, "error waiting for resource %s: %ld\n",
246 name, PTR_ERR(res));
247 return PTR_ERR(res);
248 }
249 if (time_is_before_eq_jiffies(err_at)) {
250 nfp_err(cpp, "timeout waiting for resource %s\n", name);
251 return -ETIMEDOUT;
252 }
253 if (time_is_before_eq_jiffies(warn_at)) {
254 warn_at = jiffies + NFP_MUTEX_WAIT_NEXT_WARN * HZ;
255 nfp_info(cpp, "waiting for NFP resource %s\n", name);
256 }
257 if (msleep_interruptible(10)) {
258 nfp_err(cpp, "wait for resource %s interrupted\n",
259 name);
260 return -ERESTARTSYS;
261 }
262 }
263 }
264
265
266
267
268
269
270
271 u32 nfp_resource_cpp_id(struct nfp_resource *res)
272 {
273 return res->cpp_id;
274 }
275
276
277
278
279
280
281
282 const char *nfp_resource_name(struct nfp_resource *res)
283 {
284 return res->name;
285 }
286
287
288
289
290
291
292
293 u64 nfp_resource_address(struct nfp_resource *res)
294 {
295 return res->addr;
296 }
297
298
299
300
301
302
303
304 u64 nfp_resource_size(struct nfp_resource *res)
305 {
306 return res->size;
307 }
308
309
310
311
312
313
314
315
316
317
318 int nfp_resource_table_init(struct nfp_cpp *cpp)
319 {
320 struct nfp_cpp_mutex *dev_mutex;
321 int i, err;
322
323 err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET,
324 NFP_RESOURCE_TBL_BASE);
325 if (err < 0) {
326 nfp_err(cpp, "Error: failed to reclaim resource table mutex\n");
327 return err;
328 }
329 if (err)
330 nfp_warn(cpp, "Warning: busted main resource table mutex\n");
331
332 dev_mutex = nfp_cpp_mutex_alloc(cpp, NFP_RESOURCE_TBL_TARGET,
333 NFP_RESOURCE_TBL_BASE,
334 NFP_RESOURCE_TBL_KEY);
335 if (!dev_mutex)
336 return -ENOMEM;
337
338 if (nfp_cpp_mutex_lock(dev_mutex)) {
339 nfp_err(cpp, "Error: failed to claim resource table mutex\n");
340 nfp_cpp_mutex_free(dev_mutex);
341 return -EINVAL;
342 }
343
344
345 for (i = 1; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
346 u64 addr = NFP_RESOURCE_TBL_BASE +
347 sizeof(struct nfp_resource_entry) * i;
348
349 err = nfp_cpp_mutex_reclaim(cpp, NFP_RESOURCE_TBL_TARGET, addr);
350 if (err < 0) {
351 nfp_err(cpp,
352 "Error: failed to reclaim resource %d mutex\n",
353 i);
354 goto err_unlock;
355 }
356 if (err)
357 nfp_warn(cpp, "Warning: busted resource %d mutex\n", i);
358 }
359
360 err = 0;
361 err_unlock:
362 nfp_cpp_mutex_unlock(dev_mutex);
363 nfp_cpp_mutex_free(dev_mutex);
364
365 return err;
366 }