Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2021 Marvell.
3 : : */
4 : :
5 : : #include "roc_api.h"
6 : : #include "roc_priv.h"
7 : :
8 : : static int
9 : 0 : tim_fill_msix(struct roc_tim *roc_tim, uint16_t nb_ring)
10 : : {
11 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
12 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
13 : : struct dev *dev = &sso->dev;
14 : : struct msix_offset_rsp *rsp;
15 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
16 : : int i, rc;
17 : :
18 : 0 : mbox_alloc_msg_msix_offset(mbox);
19 : : rc = mbox_process_msg(mbox, (void **)&rsp);
20 [ # # ]: 0 : if (rc) {
21 : : rc = -EIO;
22 : 0 : goto exit;
23 : : }
24 : :
25 [ # # ]: 0 : for (i = 0; i < nb_ring; i++)
26 : 0 : tim->tim_msix_offsets[i] = rsp->timlf_msixoff[i];
27 : :
28 : : rc = 0;
29 : 0 : exit:
30 : : mbox_put(mbox);
31 : 0 : return rc;
32 : : }
33 : :
34 : : static void
35 : 0 : tim_err_desc(int rc)
36 : : {
37 [ # # # # : 0 : switch (rc) {
# # # # #
# # # # #
# # # # ]
38 : 0 : case TIM_AF_NO_RINGS_LEFT:
39 : 0 : plt_err("Unable to allocate new TIM ring.");
40 : 0 : break;
41 : 0 : case TIM_AF_INVALID_NPA_PF_FUNC:
42 : 0 : plt_err("Invalid NPA pf func.");
43 : 0 : break;
44 : 0 : case TIM_AF_INVALID_SSO_PF_FUNC:
45 : 0 : plt_err("Invalid SSO pf func.");
46 : 0 : break;
47 : 0 : case TIM_AF_RING_STILL_RUNNING:
48 : 0 : plt_err("Ring busy.");
49 : 0 : break;
50 : 0 : case TIM_AF_LF_INVALID:
51 : 0 : plt_err("Invalid Ring id.");
52 : 0 : break;
53 : 0 : case TIM_AF_CSIZE_NOT_ALIGNED:
54 : 0 : plt_err("Chunk size specified needs to be multiple of 16.");
55 : 0 : break;
56 : 0 : case TIM_AF_CSIZE_TOO_SMALL:
57 : 0 : plt_err("Chunk size too small.");
58 : 0 : break;
59 : 0 : case TIM_AF_CSIZE_TOO_BIG:
60 : 0 : plt_err("Chunk size too big.");
61 : 0 : break;
62 : 0 : case TIM_AF_INTERVAL_TOO_SMALL:
63 : 0 : plt_err("Bucket traversal interval too small.");
64 : 0 : break;
65 : 0 : case TIM_AF_INVALID_BIG_ENDIAN_VALUE:
66 : 0 : plt_err("Invalid Big endian value.");
67 : 0 : break;
68 : 0 : case TIM_AF_INVALID_CLOCK_SOURCE:
69 : 0 : plt_err("Invalid Clock source specified.");
70 : 0 : break;
71 : 0 : case TIM_AF_GPIO_CLK_SRC_NOT_ENABLED:
72 : 0 : plt_err("GPIO clock source not enabled.");
73 : 0 : break;
74 : 0 : case TIM_AF_INVALID_BSIZE:
75 : 0 : plt_err("Invalid bucket size.");
76 : 0 : break;
77 : 0 : case TIM_AF_INVALID_ENABLE_PERIODIC:
78 : 0 : plt_err("Invalid bucket size.");
79 : 0 : break;
80 : 0 : case TIM_AF_INVALID_ENABLE_DONTFREE:
81 : 0 : plt_err("Invalid Don't free value.");
82 : 0 : break;
83 : 0 : case TIM_AF_ENA_DONTFRE_NSET_PERIODIC:
84 : 0 : plt_err("Don't free bit not set when periodic is enabled.");
85 : 0 : break;
86 : 0 : case TIM_AF_RING_ALREADY_DISABLED:
87 : 0 : plt_err("Ring already stopped");
88 : 0 : break;
89 : 0 : default:
90 : 0 : plt_err("Unknown Error.");
91 : : }
92 : 0 : }
93 : :
94 : : int
95 : 0 : roc_tim_capture_counters(struct roc_tim *roc_tim, uint64_t *counters, uint8_t nb_cntrs)
96 : : {
97 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
98 : : struct dev *dev = &sso->dev;
99 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
100 : : struct tim_capture_rsp *rsp;
101 : : int rc, i;
102 : :
103 : 0 : mbox_alloc_msg_tim_capture_counters(mbox);
104 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
105 [ # # ]: 0 : if (rc) {
106 : 0 : tim_err_desc(rc);
107 : : rc = -EIO;
108 : 0 : goto fail;
109 : : }
110 : :
111 [ # # ]: 0 : for (i = 0; i < nb_cntrs; i++)
112 : 0 : counters[i] = rsp->counters[i];
113 : :
114 : 0 : fail:
115 : : mbox_put(mbox);
116 : 0 : return rc;
117 : : }
118 : :
119 : : int
120 : 0 : roc_tim_lf_enable(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *start_tsc,
121 : : uint32_t *cur_bkt)
122 : : {
123 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
124 : : struct dev *dev = &sso->dev;
125 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
126 : : struct tim_enable_rsp *rsp;
127 : : struct tim_ring_req *req;
128 : : int rc = -ENOSPC;
129 : :
130 : 0 : req = mbox_alloc_msg_tim_enable_ring(mbox);
131 [ # # ]: 0 : if (req == NULL)
132 : 0 : goto fail;
133 : 0 : req->ring = ring_id;
134 : :
135 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
136 [ # # ]: 0 : if (rc) {
137 : 0 : tim_err_desc(rc);
138 : : rc = -EIO;
139 : 0 : goto fail;
140 : : }
141 : :
142 [ # # ]: 0 : if (cur_bkt)
143 : 0 : *cur_bkt = rsp->currentbucket;
144 [ # # ]: 0 : if (start_tsc)
145 : 0 : *start_tsc = rsp->timestarted;
146 : :
147 : 0 : fail:
148 : : mbox_put(mbox);
149 : 0 : return rc;
150 : : }
151 : :
152 : : int
153 : 0 : roc_tim_lf_disable(struct roc_tim *roc_tim, uint8_t ring_id)
154 : : {
155 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
156 : : struct dev *dev = &sso->dev;
157 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
158 : : struct tim_ring_req *req;
159 : : int rc = -ENOSPC;
160 : :
161 : 0 : req = mbox_alloc_msg_tim_disable_ring(mbox);
162 [ # # ]: 0 : if (req == NULL)
163 : 0 : goto fail;
164 : 0 : req->ring = ring_id;
165 : :
166 : 0 : rc = mbox_process(mbox);
167 [ # # ]: 0 : if (rc) {
168 : 0 : tim_err_desc(rc);
169 : : rc = -EIO;
170 : : }
171 : :
172 : 0 : fail:
173 : : mbox_put(mbox);
174 : 0 : return rc;
175 : : }
176 : :
177 : : uintptr_t
178 : 0 : roc_tim_lf_base_get(struct roc_tim *roc_tim, uint8_t ring_id)
179 : : {
180 : 0 : struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
181 : :
182 : 0 : return dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12);
183 : : }
184 : :
185 : : int
186 : 0 : roc_tim_lf_config(struct roc_tim *roc_tim, uint8_t ring_id,
187 : : enum roc_tim_clk_src clk_src, uint8_t ena_periodic,
188 : : uint8_t ena_dfb, uint32_t bucket_sz, uint32_t chunk_sz,
189 : : uint32_t interval, uint64_t intervalns, uint64_t clockfreq)
190 : : {
191 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
192 : : struct dev *dev = &sso->dev;
193 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
194 : : struct tim_config_req *req;
195 : : int rc = -ENOSPC;
196 : :
197 : 0 : req = mbox_alloc_msg_tim_config_ring(mbox);
198 [ # # ]: 0 : if (req == NULL)
199 : 0 : goto fail;
200 : 0 : req->ring = ring_id;
201 : 0 : req->bigendian = false;
202 : 0 : req->bucketsize = bucket_sz;
203 : 0 : req->chunksize = chunk_sz;
204 : 0 : req->clocksource = clk_src;
205 : 0 : req->enableperiodic = ena_periodic;
206 : 0 : req->enabledontfreebuffer = ena_dfb;
207 : 0 : req->interval = interval;
208 : 0 : req->intervalns = intervalns;
209 : 0 : req->clockfreq = clockfreq;
210 : 0 : req->gpioedge = TIM_GPIO_LTOH_TRANS;
211 : :
212 : 0 : rc = mbox_process(mbox);
213 [ # # ]: 0 : if (rc) {
214 : 0 : tim_err_desc(rc);
215 : : rc = -EIO;
216 : : }
217 : :
218 : 0 : fail:
219 : : mbox_put(mbox);
220 : 0 : return rc;
221 : : }
222 : :
223 : : int
224 : 0 : roc_tim_lf_interval(struct roc_tim *roc_tim, enum roc_tim_clk_src clk_src,
225 : : uint64_t clockfreq, uint64_t *intervalns,
226 : : uint64_t *interval)
227 : : {
228 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
229 : : struct dev *dev = &sso->dev;
230 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
231 : : struct tim_intvl_req *req;
232 : : struct tim_intvl_rsp *rsp;
233 : : int rc = -ENOSPC;
234 : :
235 : 0 : req = mbox_alloc_msg_tim_get_min_intvl(mbox);
236 [ # # ]: 0 : if (req == NULL)
237 : 0 : goto fail;
238 : :
239 : 0 : req->clockfreq = clockfreq;
240 : 0 : req->clocksource = clk_src;
241 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
242 [ # # ]: 0 : if (rc) {
243 : 0 : tim_err_desc(rc);
244 : : rc = -EIO;
245 : 0 : goto fail;
246 : : }
247 : :
248 : 0 : *intervalns = rsp->intvl_ns;
249 : 0 : *interval = rsp->intvl_cyc;
250 : :
251 : 0 : fail:
252 : : mbox_put(mbox);
253 : 0 : return rc;
254 : : }
255 : :
256 : : int
257 : 0 : roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk)
258 : : {
259 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
260 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
261 : : struct tim_ring_req *free_req;
262 : : struct tim_lf_alloc_req *req;
263 : : struct tim_lf_alloc_rsp *rsp;
264 : : struct dev *dev = &sso->dev;
265 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
266 : : int rc = -ENOSPC;
267 : :
268 : 0 : req = mbox_alloc_msg_tim_lf_alloc(mbox);
269 [ # # ]: 0 : if (req == NULL)
270 : 0 : goto fail;
271 : 0 : req->npa_pf_func = idev_npa_pffunc_get();
272 : 0 : req->sso_pf_func = idev_sso_pffunc_get();
273 : 0 : req->ring = ring_id;
274 : :
275 : : rc = mbox_process_msg(mbox, (void **)&rsp);
276 [ # # ]: 0 : if (rc) {
277 : 0 : tim_err_desc(rc);
278 : : rc = -EIO;
279 : 0 : goto fail;
280 : : }
281 : :
282 [ # # ]: 0 : if (clk)
283 : 0 : *clk = rsp->tenns_clk;
284 : :
285 : 0 : rc = tim_register_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
286 : 0 : tim->tim_msix_offsets[ring_id]);
287 [ # # ]: 0 : if (rc < 0) {
288 : 0 : plt_tim_dbg("Failed to register Ring[%d] IRQ", ring_id);
289 : 0 : free_req = mbox_alloc_msg_tim_lf_free(mbox);
290 [ # # ]: 0 : if (free_req == NULL) {
291 : : rc = -ENOSPC;
292 : 0 : goto fail;
293 : : }
294 : 0 : free_req->ring = ring_id;
295 : 0 : rc = mbox_process(mbox);
296 [ # # ]: 0 : if (rc)
297 : : rc = -EIO;
298 : : }
299 : :
300 : 0 : fail:
301 : 0 : mbox_put(dev->mbox);
302 : 0 : return rc;
303 : : }
304 : :
305 : : int
306 : 0 : roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id)
307 : : {
308 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
309 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
310 : : struct dev *dev = &sso->dev;
311 : : struct tim_ring_req *req;
312 : : int rc = -ENOSPC;
313 : :
314 : 0 : tim_unregister_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
315 : 0 : tim->tim_msix_offsets[ring_id]);
316 : :
317 : 0 : req = mbox_alloc_msg_tim_lf_free(mbox_get(dev->mbox));
318 [ # # ]: 0 : if (req == NULL)
319 : 0 : goto fail;
320 : 0 : req->ring = ring_id;
321 : :
322 : 0 : rc = mbox_process(dev->mbox);
323 [ # # ]: 0 : if (rc < 0) {
324 : 0 : tim_err_desc(rc);
325 : : rc = -EIO;
326 : 0 : goto fail;
327 : : }
328 : : rc = 0;
329 : :
330 : 0 : fail:
331 : 0 : mbox_put(dev->mbox);
332 : 0 : return rc;
333 : : }
334 : :
335 : : int
336 : 0 : tim_free_lf_count_get(struct dev *dev, uint16_t *nb_lfs)
337 : : {
338 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
339 : : struct free_rsrcs_rsp *rsrc_cnt;
340 : : int rc;
341 : :
342 : 0 : mbox_alloc_msg_free_rsrc_cnt(mbox);
343 : : rc = mbox_process_msg(mbox, (void **)&rsrc_cnt);
344 [ # # ]: 0 : if (rc) {
345 : 0 : plt_err("Failed to get free resource count\n");
346 : : mbox_put(mbox);
347 : 0 : return -EIO;
348 : : }
349 : :
350 : 0 : *nb_lfs = rsrc_cnt->tim;
351 : : mbox_put(mbox);
352 : :
353 : 0 : return 0;
354 : : }
355 : :
356 : : int
357 : 0 : roc_tim_init(struct roc_tim *roc_tim)
358 : : {
359 : : struct rsrc_attach_req *attach_req;
360 : : struct rsrc_detach_req *detach_req;
361 : : uint16_t nb_lfs, nb_free_lfs;
362 : : struct sso *sso;
363 : : struct dev *dev;
364 : : int rc;
365 : :
366 [ # # # # ]: 0 : if (roc_tim == NULL || roc_tim->roc_sso == NULL)
367 : : return TIM_ERR_PARAM;
368 : :
369 : : sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
370 : 0 : dev = &sso->dev;
371 : 0 : dev->roc_tim = roc_tim;
372 : : PLT_STATIC_ASSERT(sizeof(struct tim) <= TIM_MEM_SZ);
373 : 0 : nb_lfs = roc_tim->nb_lfs;
374 : :
375 : 0 : rc = tim_free_lf_count_get(dev, &nb_free_lfs);
376 [ # # ]: 0 : if (rc) {
377 : 0 : plt_tim_dbg("Failed to get TIM resource count");
378 : : nb_lfs = 0;
379 : 0 : return nb_lfs;
380 : : }
381 : :
382 [ # # # # ]: 0 : if (nb_lfs && (nb_free_lfs < nb_lfs)) {
383 : 0 : plt_tim_dbg("Requested LFs : %d Available LFs : %d", nb_lfs, nb_free_lfs);
384 : : nb_lfs = 0;
385 : 0 : return nb_lfs;
386 : : }
387 : :
388 : 0 : mbox_get(dev->mbox);
389 : 0 : attach_req = mbox_alloc_msg_attach_resources(dev->mbox);
390 [ # # ]: 0 : if (attach_req == NULL) {
391 : : nb_lfs = 0;
392 : 0 : goto fail;
393 : : }
394 : 0 : attach_req->modify = true;
395 [ # # ]: 0 : attach_req->timlfs = nb_lfs ? nb_lfs : nb_free_lfs;
396 : 0 : nb_lfs = attach_req->timlfs;
397 : :
398 : 0 : rc = mbox_process(dev->mbox);
399 [ # # ]: 0 : if (rc) {
400 : 0 : plt_err("Unable to attach TIM LFs.");
401 : : nb_lfs = 0;
402 : 0 : goto fail;
403 : : }
404 : :
405 : 0 : mbox_put(dev->mbox);
406 : 0 : rc = tim_fill_msix(roc_tim, nb_lfs);
407 [ # # ]: 0 : if (rc < 0) {
408 : 0 : plt_err("Unable to get TIM MSIX vectors");
409 : :
410 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox_get(dev->mbox));
411 [ # # ]: 0 : if (detach_req == NULL) {
412 : : nb_lfs = 0;
413 : 0 : goto fail;
414 : : }
415 : 0 : detach_req->partial = true;
416 : 0 : detach_req->timlfs = true;
417 : 0 : mbox_process(dev->mbox);
418 : : nb_lfs = 0;
419 : : } else {
420 : 0 : goto done;
421 : : }
422 : :
423 : 0 : fail:
424 : 0 : mbox_put(dev->mbox);
425 : 0 : done:
426 : 0 : roc_tim->nb_lfs = nb_lfs;
427 : 0 : return nb_lfs;
428 : : }
429 : :
430 : : void
431 : 0 : roc_tim_fini(struct roc_tim *roc_tim)
432 : : {
433 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
434 : : struct rsrc_detach_req *detach_req;
435 : : struct dev *dev = &sso->dev;
436 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
437 : :
438 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox);
439 : : PLT_ASSERT(detach_req);
440 : 0 : detach_req->partial = true;
441 : 0 : detach_req->timlfs = true;
442 : :
443 : 0 : mbox_process(mbox);
444 : : mbox_put(mbox);
445 : 0 : }
|