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