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_lf_enable(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *start_tsc,
96 : : uint32_t *cur_bkt)
97 : : {
98 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
99 : : struct dev *dev = &sso->dev;
100 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
101 : : struct tim_enable_rsp *rsp;
102 : : struct tim_ring_req *req;
103 : : int rc = -ENOSPC;
104 : :
105 : 0 : req = mbox_alloc_msg_tim_enable_ring(mbox);
106 [ # # ]: 0 : if (req == NULL)
107 : 0 : goto fail;
108 : 0 : req->ring = ring_id;
109 : :
110 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
111 [ # # ]: 0 : if (rc) {
112 : 0 : tim_err_desc(rc);
113 : : rc = -EIO;
114 : 0 : goto fail;
115 : : }
116 : :
117 [ # # ]: 0 : if (cur_bkt)
118 : 0 : *cur_bkt = rsp->currentbucket;
119 [ # # ]: 0 : if (start_tsc)
120 : 0 : *start_tsc = rsp->timestarted;
121 : :
122 : 0 : fail:
123 : : mbox_put(mbox);
124 : 0 : return rc;
125 : : }
126 : :
127 : : int
128 : 0 : roc_tim_lf_disable(struct roc_tim *roc_tim, uint8_t ring_id)
129 : : {
130 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
131 : : struct dev *dev = &sso->dev;
132 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
133 : : struct tim_ring_req *req;
134 : : int rc = -ENOSPC;
135 : :
136 : 0 : req = mbox_alloc_msg_tim_disable_ring(mbox);
137 [ # # ]: 0 : if (req == NULL)
138 : 0 : goto fail;
139 : 0 : req->ring = ring_id;
140 : :
141 : 0 : rc = mbox_process(dev->mbox);
142 [ # # ]: 0 : if (rc) {
143 : 0 : tim_err_desc(rc);
144 : : rc = -EIO;
145 : : }
146 : :
147 : 0 : fail:
148 : : mbox_put(mbox);
149 : 0 : return rc;
150 : : }
151 : :
152 : : uintptr_t
153 : 0 : roc_tim_lf_base_get(struct roc_tim *roc_tim, uint8_t ring_id)
154 : : {
155 : 0 : struct dev *dev = &roc_sso_to_sso_priv(roc_tim->roc_sso)->dev;
156 : :
157 : 0 : return dev->bar2 + (RVU_BLOCK_ADDR_TIM << 20 | ring_id << 12);
158 : : }
159 : :
160 : : int
161 : 0 : roc_tim_lf_config(struct roc_tim *roc_tim, uint8_t ring_id,
162 : : enum roc_tim_clk_src clk_src, uint8_t ena_periodic,
163 : : uint8_t ena_dfb, uint32_t bucket_sz, uint32_t chunk_sz,
164 : : uint32_t interval, uint64_t intervalns, uint64_t clockfreq)
165 : : {
166 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
167 : : struct dev *dev = &sso->dev;
168 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
169 : : struct tim_config_req *req;
170 : : int rc = -ENOSPC;
171 : :
172 : 0 : req = mbox_alloc_msg_tim_config_ring(mbox);
173 [ # # ]: 0 : if (req == NULL)
174 : 0 : goto fail;
175 : 0 : req->ring = ring_id;
176 : 0 : req->bigendian = false;
177 : 0 : req->bucketsize = bucket_sz;
178 : 0 : req->chunksize = chunk_sz;
179 : 0 : req->clocksource = clk_src;
180 : 0 : req->enableperiodic = ena_periodic;
181 : 0 : req->enabledontfreebuffer = ena_dfb;
182 : 0 : req->interval = interval;
183 : 0 : req->intervalns = intervalns;
184 : 0 : req->clockfreq = clockfreq;
185 : 0 : req->gpioedge = TIM_GPIO_LTOH_TRANS;
186 : :
187 : 0 : rc = mbox_process(mbox);
188 [ # # ]: 0 : if (rc) {
189 : 0 : tim_err_desc(rc);
190 : : rc = -EIO;
191 : : }
192 : :
193 : 0 : fail:
194 : : mbox_put(mbox);
195 : 0 : return rc;
196 : : }
197 : :
198 : : int
199 : 0 : roc_tim_lf_interval(struct roc_tim *roc_tim, enum roc_tim_clk_src clk_src,
200 : : uint64_t clockfreq, uint64_t *intervalns,
201 : : uint64_t *interval)
202 : : {
203 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
204 : : struct dev *dev = &sso->dev;
205 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
206 : : struct tim_intvl_req *req;
207 : : struct tim_intvl_rsp *rsp;
208 : : int rc = -ENOSPC;
209 : :
210 : 0 : req = mbox_alloc_msg_tim_get_min_intvl(mbox);
211 [ # # ]: 0 : if (req == NULL)
212 : 0 : goto fail;
213 : :
214 : 0 : req->clockfreq = clockfreq;
215 : 0 : req->clocksource = clk_src;
216 : 0 : rc = mbox_process_msg(dev->mbox, (void **)&rsp);
217 [ # # ]: 0 : if (rc) {
218 : 0 : tim_err_desc(rc);
219 : : rc = -EIO;
220 : 0 : goto fail;
221 : : }
222 : :
223 : 0 : *intervalns = rsp->intvl_ns;
224 : 0 : *interval = rsp->intvl_cyc;
225 : :
226 : 0 : fail:
227 : : mbox_put(mbox);
228 : 0 : return rc;
229 : : }
230 : :
231 : : int
232 : 0 : roc_tim_lf_alloc(struct roc_tim *roc_tim, uint8_t ring_id, uint64_t *clk)
233 : : {
234 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
235 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
236 : : struct tim_ring_req *free_req;
237 : : struct tim_lf_alloc_req *req;
238 : : struct tim_lf_alloc_rsp *rsp;
239 : : struct dev *dev = &sso->dev;
240 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
241 : : int rc = -ENOSPC;
242 : :
243 : 0 : req = mbox_alloc_msg_tim_lf_alloc(mbox);
244 [ # # ]: 0 : if (req == NULL)
245 : 0 : goto fail;
246 : 0 : req->npa_pf_func = idev_npa_pffunc_get();
247 : 0 : req->sso_pf_func = idev_sso_pffunc_get();
248 : 0 : req->ring = ring_id;
249 : :
250 : : rc = mbox_process_msg(mbox, (void **)&rsp);
251 [ # # ]: 0 : if (rc) {
252 : 0 : tim_err_desc(rc);
253 : : rc = -EIO;
254 : 0 : goto fail;
255 : : }
256 : :
257 [ # # ]: 0 : if (clk)
258 : 0 : *clk = rsp->tenns_clk;
259 : :
260 : 0 : rc = tim_register_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
261 : 0 : tim->tim_msix_offsets[ring_id]);
262 [ # # ]: 0 : if (rc < 0) {
263 : 0 : plt_tim_dbg("Failed to register Ring[%d] IRQ", ring_id);
264 : 0 : free_req = mbox_alloc_msg_tim_lf_free(mbox);
265 [ # # ]: 0 : if (free_req == NULL) {
266 : : rc = -ENOSPC;
267 : 0 : goto fail;
268 : : }
269 : 0 : free_req->ring = ring_id;
270 : 0 : rc = mbox_process(mbox);
271 [ # # ]: 0 : if (rc)
272 : : rc = -EIO;
273 : : }
274 : :
275 : 0 : fail:
276 : 0 : mbox_put(dev->mbox);
277 : 0 : return rc;
278 : : }
279 : :
280 : : int
281 : 0 : roc_tim_lf_free(struct roc_tim *roc_tim, uint8_t ring_id)
282 : : {
283 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
284 : : struct tim *tim = roc_tim_to_tim_priv(roc_tim);
285 : : struct dev *dev = &sso->dev;
286 : : struct tim_ring_req *req;
287 : : int rc = -ENOSPC;
288 : :
289 : 0 : tim_unregister_irq_priv(roc_tim, sso->pci_dev->intr_handle, ring_id,
290 : 0 : tim->tim_msix_offsets[ring_id]);
291 : :
292 : 0 : req = mbox_alloc_msg_tim_lf_free(mbox_get(dev->mbox));
293 [ # # ]: 0 : if (req == NULL)
294 : 0 : goto fail;
295 : 0 : req->ring = ring_id;
296 : :
297 : 0 : rc = mbox_process(dev->mbox);
298 [ # # ]: 0 : if (rc < 0) {
299 : 0 : tim_err_desc(rc);
300 : : rc = -EIO;
301 : 0 : goto fail;
302 : : }
303 : : rc = 0;
304 : :
305 : 0 : fail:
306 : 0 : mbox_put(dev->mbox);
307 : 0 : return rc;
308 : : }
309 : :
310 : : int
311 : 0 : tim_free_lf_count_get(struct dev *dev, uint16_t *nb_lfs)
312 : : {
313 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
314 : : struct free_rsrcs_rsp *rsrc_cnt;
315 : : int rc;
316 : :
317 : 0 : mbox_alloc_msg_free_rsrc_cnt(mbox);
318 : : rc = mbox_process_msg(mbox, (void **)&rsrc_cnt);
319 [ # # ]: 0 : if (rc) {
320 : 0 : plt_err("Failed to get free resource count\n");
321 : : mbox_put(mbox);
322 : 0 : return -EIO;
323 : : }
324 : :
325 : 0 : *nb_lfs = rsrc_cnt->tim;
326 : : mbox_put(mbox);
327 : :
328 : 0 : return 0;
329 : : }
330 : :
331 : : int
332 : 0 : roc_tim_init(struct roc_tim *roc_tim)
333 : : {
334 : : struct rsrc_attach_req *attach_req;
335 : : struct rsrc_detach_req *detach_req;
336 : : uint16_t nb_lfs, nb_free_lfs;
337 : : struct sso *sso;
338 : : struct dev *dev;
339 : : int rc;
340 : :
341 [ # # # # ]: 0 : if (roc_tim == NULL || roc_tim->roc_sso == NULL)
342 : : return TIM_ERR_PARAM;
343 : :
344 : : sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
345 : 0 : dev = &sso->dev;
346 : 0 : dev->roc_tim = roc_tim;
347 : : PLT_STATIC_ASSERT(sizeof(struct tim) <= TIM_MEM_SZ);
348 : 0 : nb_lfs = roc_tim->nb_lfs;
349 : :
350 : 0 : rc = tim_free_lf_count_get(dev, &nb_free_lfs);
351 [ # # ]: 0 : if (rc) {
352 : 0 : plt_tim_dbg("Failed to get TIM resource count");
353 : : nb_lfs = 0;
354 : 0 : return nb_lfs;
355 : : }
356 : :
357 [ # # # # ]: 0 : if (nb_lfs && (nb_free_lfs < nb_lfs)) {
358 : 0 : plt_tim_dbg("Requested LFs : %d Available LFs : %d", nb_lfs, nb_free_lfs);
359 : : nb_lfs = 0;
360 : 0 : return nb_lfs;
361 : : }
362 : :
363 : 0 : mbox_get(dev->mbox);
364 : 0 : attach_req = mbox_alloc_msg_attach_resources(dev->mbox);
365 [ # # ]: 0 : if (attach_req == NULL) {
366 : : nb_lfs = 0;
367 : 0 : goto fail;
368 : : }
369 : 0 : attach_req->modify = true;
370 [ # # ]: 0 : attach_req->timlfs = nb_lfs ? nb_lfs : nb_free_lfs;
371 : 0 : nb_lfs = attach_req->timlfs;
372 : :
373 : 0 : rc = mbox_process(dev->mbox);
374 [ # # ]: 0 : if (rc) {
375 : 0 : plt_err("Unable to attach TIM LFs.");
376 : : nb_lfs = 0;
377 : 0 : goto fail;
378 : : }
379 : :
380 : 0 : mbox_put(dev->mbox);
381 : 0 : rc = tim_fill_msix(roc_tim, nb_lfs);
382 [ # # ]: 0 : if (rc < 0) {
383 : 0 : plt_err("Unable to get TIM MSIX vectors");
384 : :
385 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox_get(dev->mbox));
386 [ # # ]: 0 : if (detach_req == NULL) {
387 : : nb_lfs = 0;
388 : 0 : goto fail;
389 : : }
390 : 0 : detach_req->partial = true;
391 : 0 : detach_req->timlfs = true;
392 : 0 : mbox_process(dev->mbox);
393 : : nb_lfs = 0;
394 : : } else {
395 : 0 : goto done;
396 : : }
397 : :
398 : 0 : fail:
399 : 0 : mbox_put(dev->mbox);
400 : 0 : done:
401 : 0 : roc_tim->nb_lfs = nb_lfs;
402 : 0 : return nb_lfs;
403 : : }
404 : :
405 : : void
406 : 0 : roc_tim_fini(struct roc_tim *roc_tim)
407 : : {
408 : 0 : struct sso *sso = roc_sso_to_sso_priv(roc_tim->roc_sso);
409 : : struct rsrc_detach_req *detach_req;
410 : : struct dev *dev = &sso->dev;
411 : 0 : struct mbox *mbox = mbox_get(dev->mbox);
412 : :
413 : 0 : detach_req = mbox_alloc_msg_detach_resources(mbox);
414 : : PLT_ASSERT(detach_req);
415 : 0 : detach_req->partial = true;
416 : 0 : detach_req->timlfs = true;
417 : :
418 : 0 : mbox_process(mbox);
419 : : mbox_put(mbox);
420 : 0 : }
|