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