Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : :
5 : : #include <rte_thash.h>
6 : :
7 : : #include <cnxk_eswitch.h>
8 : : #include <cnxk_rep.h>
9 : :
10 : : #define CNXK_NIX_DEF_SQ_COUNT 512
11 : :
12 : : int
13 : 0 : cnxk_eswitch_representor_id(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func,
14 : : uint16_t *rep_id)
15 : : {
16 : : struct cnxk_esw_repr_hw_info *repr_info;
17 : : int rc = 0;
18 : :
19 : 0 : repr_info = cnxk_eswitch_representor_hw_info(eswitch_dev, hw_func);
20 [ # # ]: 0 : if (!repr_info) {
21 : 0 : plt_warn("Failed to get representor group for %x", hw_func);
22 : : rc = -ENOENT;
23 : 0 : goto fail;
24 : : }
25 : :
26 : 0 : *rep_id = repr_info->rep_id;
27 : :
28 : 0 : return 0;
29 : : fail:
30 : 0 : return rc;
31 : : }
32 : :
33 : : struct cnxk_esw_repr_hw_info *
34 : 0 : cnxk_eswitch_representor_hw_info(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func)
35 : : {
36 : : struct cnxk_eswitch_devargs *esw_da;
37 : : int i, j;
38 : :
39 [ # # ]: 0 : if (!eswitch_dev)
40 : : return NULL;
41 : :
42 : : /* Traversing the initialized represented list */
43 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_esw_da; i++) {
44 : : esw_da = &eswitch_dev->esw_da[i];
45 [ # # ]: 0 : for (j = 0; j < esw_da->nb_repr_ports; j++) {
46 [ # # ]: 0 : if (esw_da->repr_hw_info[j].hw_func == hw_func)
47 : 0 : return &esw_da->repr_hw_info[j];
48 : : }
49 : : }
50 : : return NULL;
51 : : }
52 : :
53 : : static int
54 : 0 : eswitch_hw_rsrc_cleanup(struct cnxk_eswitch_dev *eswitch_dev, struct rte_pci_device *pci_dev)
55 : : {
56 : : struct roc_nix *nix;
57 : : int rc = 0;
58 : :
59 : 0 : nix = &eswitch_dev->nix;
60 : :
61 : 0 : roc_nix_unregister_queue_irqs(nix);
62 : 0 : roc_nix_tm_fini(nix);
63 : 0 : rc = roc_nix_lf_free(nix);
64 [ # # ]: 0 : if (rc) {
65 : 0 : plt_err("Failed to cleanup sq, rc %d", rc);
66 : 0 : goto exit;
67 : : }
68 : :
69 : : /* Check if this device is hosting common resource */
70 : 0 : nix = roc_idev_npa_nix_get();
71 [ # # # # ]: 0 : if (!nix || nix->pci_dev != pci_dev) {
72 : : rc = 0;
73 : 0 : goto exit;
74 : : }
75 : :
76 : : /* Try nix fini now */
77 : 0 : rc = roc_nix_dev_fini(nix);
78 [ # # ]: 0 : if (rc == -EAGAIN) {
79 : 0 : plt_info("Common resource in use by other devices %s", pci_dev->name);
80 : 0 : goto exit;
81 [ # # ]: 0 : } else if (rc) {
82 : 0 : plt_err("Failed in nix dev fini, rc=%d", rc);
83 : 0 : goto exit;
84 : : }
85 : :
86 : 0 : rte_free(eswitch_dev->txq);
87 : 0 : rte_free(eswitch_dev->rxq);
88 : 0 : rte_free(eswitch_dev->cxq);
89 : :
90 : 0 : exit:
91 : 0 : return rc;
92 : : }
93 : :
94 : : static int
95 : 0 : cnxk_eswitch_dev_remove(struct rte_pci_device *pci_dev)
96 : : {
97 : : struct cnxk_eswitch_dev *eswitch_dev;
98 : : int rc = 0;
99 : :
100 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
101 : : return 0;
102 : :
103 : : eswitch_dev = cnxk_eswitch_pmd_priv();
104 [ # # ]: 0 : if (!eswitch_dev) {
105 : : rc = -EINVAL;
106 : 0 : goto exit;
107 : : }
108 : :
109 : : /* Remove representor devices associated with PF */
110 [ # # ]: 0 : if (eswitch_dev->repr_cnt.nb_repr_created) {
111 : : /* Exiting the rep msg ctrl thread */
112 [ # # ]: 0 : if (eswitch_dev->start_ctrl_msg_thrd) {
113 : : uint32_t sunlen;
114 : 0 : struct sockaddr_un sun = {0};
115 : : int sock_fd = 0;
116 : :
117 : 0 : eswitch_dev->start_ctrl_msg_thrd = false;
118 [ # # ]: 0 : if (!eswitch_dev->client_connected) {
119 : 0 : plt_esw_dbg("Establishing connection for teardown");
120 : 0 : sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
121 [ # # ]: 0 : if (sock_fd == -1) {
122 : 0 : plt_err("Failed to open socket. err %d", -errno);
123 : 0 : return -errno;
124 : : }
125 : 0 : sun.sun_family = AF_UNIX;
126 : : sunlen = sizeof(struct sockaddr_un);
127 : : strncpy(sun.sun_path, CNXK_ESWITCH_CTRL_MSG_SOCK_PATH,
128 : : sizeof(sun.sun_path) - 1);
129 : :
130 [ # # ]: 0 : if (connect(sock_fd, (struct sockaddr *)&sun, sunlen) < 0) {
131 : 0 : plt_err("Failed to connect socket: %s, err %d",
132 : : CNXK_ESWITCH_CTRL_MSG_SOCK_PATH, errno);
133 : 0 : close(sock_fd);
134 : 0 : return -errno;
135 : : }
136 : : }
137 : 0 : rte_thread_join(eswitch_dev->rep_ctrl_msg_thread, NULL);
138 [ # # ]: 0 : if (!eswitch_dev->client_connected)
139 : 0 : close(sock_fd);
140 : : }
141 : :
142 [ # # ]: 0 : if (eswitch_dev->repte_msg_proc.start_thread) {
143 : 0 : eswitch_dev->repte_msg_proc.start_thread = false;
144 : 0 : pthread_cond_signal(&eswitch_dev->repte_msg_proc.repte_msg_cond);
145 : 0 : rte_thread_join(eswitch_dev->repte_msg_proc.repte_msg_thread, NULL);
146 : 0 : pthread_mutex_destroy(&eswitch_dev->repte_msg_proc.mutex);
147 : 0 : pthread_cond_destroy(&eswitch_dev->repte_msg_proc.repte_msg_cond);
148 : : }
149 : :
150 : : /* Remove representor devices associated with PF */
151 : 0 : cnxk_rep_dev_remove(eswitch_dev);
152 : : }
153 : :
154 : : /* Cleanup NPC rxtx flow rules */
155 : 0 : cnxk_eswitch_flow_rules_remove_list(eswitch_dev, &eswitch_dev->esw_flow_list,
156 : 0 : eswitch_dev->npc.pf_func);
157 : :
158 : : /* Cleanup HW resources */
159 : 0 : eswitch_hw_rsrc_cleanup(eswitch_dev, pci_dev);
160 : :
161 : 0 : rte_free(eswitch_dev);
162 : : exit:
163 : : return rc;
164 : : }
165 : :
166 : : int
167 : 0 : cnxk_eswitch_nix_rsrc_start(struct cnxk_eswitch_dev *eswitch_dev)
168 : : {
169 : : int rc;
170 : :
171 : : /* Install eswitch PF mcam rules */
172 : 0 : rc = cnxk_eswitch_pfvf_flow_rules_install(eswitch_dev, false);
173 [ # # ]: 0 : if (rc) {
174 : 0 : plt_err("Failed to install rxtx rules, rc %d", rc);
175 : 0 : goto done;
176 : : }
177 : :
178 : : /* Configure TPID for Eswitch PF LFs */
179 : 0 : rc = roc_eswitch_nix_vlan_tpid_set(&eswitch_dev->nix, ROC_NIX_VLAN_TYPE_OUTER,
180 : : CNXK_ESWITCH_VLAN_TPID, false);
181 [ # # ]: 0 : if (rc) {
182 : 0 : plt_err("Failed to configure tpid, rc %d", rc);
183 : 0 : goto done;
184 : : }
185 : :
186 : : /* Enable Rx in NPC */
187 : 0 : rc = roc_nix_npc_rx_ena_dis(&eswitch_dev->nix, true);
188 [ # # ]: 0 : if (rc) {
189 : 0 : plt_err("Failed to enable NPC rx %d", rc);
190 : 0 : goto done;
191 : : }
192 : :
193 : 0 : rc = roc_npc_mcam_enable_all_entries(&eswitch_dev->npc, 1);
194 [ # # ]: 0 : if (rc) {
195 : 0 : plt_err("Failed to enable NPC entries %d", rc);
196 : 0 : goto done;
197 : : }
198 : :
199 : 0 : done:
200 : 0 : return 0;
201 : : }
202 : :
203 : : int
204 : 0 : cnxk_eswitch_txq_start(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
205 : : {
206 : 0 : struct roc_nix_sq *sq = &eswitch_dev->txq[qid].sqs;
207 : : int rc = -EINVAL;
208 : :
209 [ # # ]: 0 : if (eswitch_dev->txq[qid].state == CNXK_ESWITCH_QUEUE_STATE_STARTED)
210 : : return 0;
211 : :
212 [ # # ]: 0 : if (eswitch_dev->txq[qid].state != CNXK_ESWITCH_QUEUE_STATE_CONFIGURED) {
213 : 0 : plt_err("Eswitch txq %d not configured yet", qid);
214 : 0 : goto done;
215 : : }
216 : :
217 : 0 : rc = roc_nix_sq_ena_dis(sq, true);
218 [ # # ]: 0 : if (rc) {
219 : 0 : plt_err("Failed to enable sq aura fc, txq=%u, rc=%d", qid, rc);
220 : 0 : goto done;
221 : : }
222 : :
223 : 0 : eswitch_dev->txq[qid].state = CNXK_ESWITCH_QUEUE_STATE_STARTED;
224 : : done:
225 : : return rc;
226 : : }
227 : :
228 : : int
229 : 0 : cnxk_eswitch_txq_stop(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
230 : : {
231 : 0 : struct roc_nix_sq *sq = &eswitch_dev->txq[qid].sqs;
232 : : int rc = -EINVAL;
233 : :
234 [ # # ]: 0 : if (eswitch_dev->txq[qid].state == CNXK_ESWITCH_QUEUE_STATE_STOPPED ||
235 : : eswitch_dev->txq[qid].state == CNXK_ESWITCH_QUEUE_STATE_RELEASED)
236 : : return 0;
237 : :
238 [ # # ]: 0 : if (eswitch_dev->txq[qid].state != CNXK_ESWITCH_QUEUE_STATE_STARTED) {
239 : 0 : plt_err("Eswitch txq %d not started", qid);
240 : 0 : goto done;
241 : : }
242 : :
243 : 0 : rc = roc_nix_sq_ena_dis(sq, false);
244 [ # # ]: 0 : if (rc) {
245 : 0 : plt_err("Failed to disable sqb aura fc, txq=%u, rc=%d", qid, rc);
246 : 0 : goto done;
247 : : }
248 : :
249 : 0 : eswitch_dev->txq[qid].state = CNXK_ESWITCH_QUEUE_STATE_STOPPED;
250 : : done:
251 : : return rc;
252 : : }
253 : :
254 : : int
255 : 0 : cnxk_eswitch_rxq_start(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
256 : : {
257 : 0 : struct roc_nix_rq *rq = &eswitch_dev->rxq[qid].rqs;
258 : : int rc = -EINVAL;
259 : :
260 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state == CNXK_ESWITCH_QUEUE_STATE_STARTED)
261 : : return 0;
262 : :
263 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state != CNXK_ESWITCH_QUEUE_STATE_CONFIGURED) {
264 : 0 : plt_err("Eswitch rxq %d not configured yet", qid);
265 : 0 : goto done;
266 : : }
267 : :
268 : 0 : rc = roc_nix_rq_ena_dis(rq, true);
269 [ # # ]: 0 : if (rc) {
270 : 0 : plt_err("Failed to enable rxq=%u, rc=%d", qid, rc);
271 : 0 : goto done;
272 : : }
273 : :
274 : 0 : eswitch_dev->rxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_STARTED;
275 : : done:
276 : : return rc;
277 : : }
278 : :
279 : : int
280 : 0 : cnxk_eswitch_rxq_stop(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
281 : : {
282 : 0 : struct roc_nix_rq *rq = &eswitch_dev->rxq[qid].rqs;
283 : : int rc = -EINVAL;
284 : :
285 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state == CNXK_ESWITCH_QUEUE_STATE_STOPPED ||
286 : : eswitch_dev->rxq[qid].state == CNXK_ESWITCH_QUEUE_STATE_RELEASED)
287 : : return 0;
288 : :
289 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state != CNXK_ESWITCH_QUEUE_STATE_STARTED) {
290 : 0 : plt_err("Eswitch rxq %d not started", qid);
291 : 0 : goto done;
292 : : }
293 : :
294 : 0 : rc = roc_nix_rq_ena_dis(rq, false);
295 [ # # ]: 0 : if (rc) {
296 : 0 : plt_err("Failed to disable rxq=%u, rc=%d", qid, rc);
297 : 0 : goto done;
298 : : }
299 : :
300 : 0 : eswitch_dev->rxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_STOPPED;
301 : : done:
302 : : return rc;
303 : : }
304 : :
305 : : int
306 : 0 : cnxk_eswitch_rxq_release(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
307 : : {
308 : : struct roc_nix_rq *rq;
309 : : struct roc_nix_cq *cq;
310 : : int rc;
311 : :
312 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state == CNXK_ESWITCH_QUEUE_STATE_RELEASED)
313 : : return 0;
314 : :
315 : : /* Cleanup ROC SQ */
316 : 0 : rq = &eswitch_dev->rxq[qid].rqs;
317 : 0 : rc = roc_nix_rq_fini(rq);
318 [ # # ]: 0 : if (rc) {
319 : 0 : plt_err("Failed to cleanup sq, rc=%d", rc);
320 : 0 : goto fail;
321 : : }
322 : :
323 : 0 : eswitch_dev->rxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_RELEASED;
324 : :
325 : : /* Cleanup ROC CQ */
326 : 0 : cq = &eswitch_dev->cxq[qid].cqs;
327 : 0 : rc = roc_nix_cq_fini(cq);
328 [ # # ]: 0 : if (rc) {
329 : 0 : plt_err("Failed to cleanup cq, rc=%d", rc);
330 : 0 : goto fail;
331 : : }
332 : :
333 : 0 : eswitch_dev->cxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_RELEASED;
334 : : fail:
335 : : return rc;
336 : : }
337 : :
338 : : int
339 : 0 : cnxk_eswitch_rxq_setup(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid, uint16_t nb_desc,
340 : : const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mp)
341 : : {
342 : 0 : struct roc_nix *nix = &eswitch_dev->nix;
343 : : struct rte_mempool *lpb_pool = mp;
344 : : struct rte_mempool_ops *ops;
345 : : const char *platform_ops;
346 : : struct roc_nix_rq *rq;
347 : : struct roc_nix_cq *cq;
348 : : uint16_t first_skip;
349 : : int rc = -EINVAL;
350 : :
351 [ # # ]: 0 : if (eswitch_dev->rxq[qid].state != CNXK_ESWITCH_QUEUE_STATE_RELEASED ||
352 [ # # ]: 0 : eswitch_dev->cxq[qid].state != CNXK_ESWITCH_QUEUE_STATE_RELEASED) {
353 : 0 : plt_err("Queue %d is in invalid state %d, cannot be setup", qid,
354 : : eswitch_dev->txq[qid].state);
355 : 0 : goto fail;
356 : : }
357 : :
358 : : RTE_SET_USED(rx_conf);
359 : 0 : platform_ops = rte_mbuf_platform_mempool_ops();
360 : : /* This driver needs cnxk_npa mempool ops to work */
361 : 0 : ops = rte_mempool_get_ops(lpb_pool->ops_index);
362 [ # # ]: 0 : if (strncmp(ops->name, platform_ops, RTE_MEMPOOL_OPS_NAMESIZE)) {
363 : 0 : plt_err("mempool ops should be of cnxk_npa type");
364 : 0 : goto fail;
365 : : }
366 : :
367 [ # # ]: 0 : if (lpb_pool->pool_id == 0) {
368 : 0 : plt_err("Invalid pool_id");
369 : 0 : goto fail;
370 : : }
371 : :
372 : : /* Setup ROC CQ */
373 : 0 : cq = &eswitch_dev->cxq[qid].cqs;
374 : : memset(cq, 0, sizeof(struct roc_nix_cq));
375 : 0 : cq->qid = qid;
376 : 0 : cq->nb_desc = nb_desc;
377 : 0 : rc = roc_nix_cq_init(nix, cq);
378 [ # # ]: 0 : if (rc) {
379 : 0 : plt_err("Failed to init roc cq for rq=%d, rc=%d", qid, rc);
380 : 0 : goto fail;
381 : : }
382 : 0 : eswitch_dev->cxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_CONFIGURED;
383 : :
384 : : /* Setup ROC RQ */
385 [ # # ]: 0 : rq = &eswitch_dev->rxq[qid].rqs;
386 : : memset(rq, 0, sizeof(struct roc_nix_rq));
387 : 0 : rq->qid = qid;
388 : 0 : rq->cqid = cq->qid;
389 : 0 : rq->aura_handle = lpb_pool->pool_id;
390 : 0 : rq->flow_tag_width = 32;
391 : : rq->sso_ena = false;
392 : 0 : rq->pb_caching = ROC_NIX_RQ_DEFAULT_PB_CACHING;
393 [ # # ]: 0 : rq->wqe_caching = ROC_NIX_RQ_DEFAULT_WQE_CACHING;
394 : :
395 : : /* Calculate first mbuf skip */
396 : : first_skip = (sizeof(struct rte_mbuf));
397 : : first_skip += RTE_PKTMBUF_HEADROOM;
398 : 0 : first_skip += rte_pktmbuf_priv_size(lpb_pool);
399 : 0 : rq->first_skip = first_skip;
400 : 0 : rq->later_skip = sizeof(struct rte_mbuf) + rte_pktmbuf_priv_size(lpb_pool);
401 [ # # ]: 0 : rq->lpb_size = lpb_pool->elt_size;
402 [ # # ]: 0 : if (roc_errata_nix_no_meta_aura())
403 : 0 : rq->lpb_drop_ena = true;
404 : :
405 : 0 : rc = roc_nix_rq_init(nix, rq, true);
406 [ # # ]: 0 : if (rc) {
407 : 0 : plt_err("Failed to init roc rq for rq=%d, rc=%d", qid, rc);
408 : 0 : goto cq_fini;
409 : : }
410 : 0 : eswitch_dev->rxq[qid].state = CNXK_ESWITCH_QUEUE_STATE_CONFIGURED;
411 : :
412 : 0 : return 0;
413 : : cq_fini:
414 : 0 : rc |= roc_nix_cq_fini(cq);
415 : : fail:
416 : : return rc;
417 : : }
418 : :
419 : : int
420 : 0 : cnxk_eswitch_txq_release(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid)
421 : : {
422 : : struct roc_nix_sq *sq;
423 : : int rc = 0;
424 : :
425 [ # # ]: 0 : if (eswitch_dev->txq[qid].state == CNXK_ESWITCH_QUEUE_STATE_RELEASED)
426 : : return 0;
427 : :
428 : : /* Cleanup ROC SQ */
429 : 0 : sq = &eswitch_dev->txq[qid].sqs;
430 : 0 : rc = roc_nix_sq_fini(sq);
431 [ # # ]: 0 : if (rc) {
432 : 0 : plt_err("Failed to cleanup sq, rc=%d", rc);
433 : 0 : goto fail;
434 : : }
435 : :
436 : 0 : eswitch_dev->txq[qid].state = CNXK_ESWITCH_QUEUE_STATE_RELEASED;
437 : : fail:
438 : : return rc;
439 : : }
440 : :
441 : : int
442 : 0 : cnxk_eswitch_txq_setup(struct cnxk_eswitch_dev *eswitch_dev, uint16_t qid, uint16_t nb_desc,
443 : : const struct rte_eth_txconf *tx_conf)
444 : : {
445 : : struct roc_nix_sq *sq;
446 : : int rc = 0;
447 : :
448 [ # # ]: 0 : if (eswitch_dev->txq[qid].state != CNXK_ESWITCH_QUEUE_STATE_RELEASED) {
449 : 0 : plt_err("Queue %d is in invalid state %d, cannot be setup", qid,
450 : : eswitch_dev->txq[qid].state);
451 : : rc = -EINVAL;
452 : 0 : goto fail;
453 : : }
454 : : RTE_SET_USED(tx_conf);
455 : : /* Setup ROC SQ */
456 [ # # ]: 0 : sq = &eswitch_dev->txq[qid].sqs;
457 : : memset(sq, 0, sizeof(struct roc_nix_sq));
458 : 0 : sq->qid = qid;
459 : 0 : sq->nb_desc = nb_desc;
460 : : sq->max_sqe_sz = NIX_MAXSQESZ_W16;
461 [ # # ]: 0 : if (sq->nb_desc >= CNXK_NIX_DEF_SQ_COUNT)
462 : 0 : sq->fc_hyst_bits = 0x1;
463 : :
464 : 0 : rc = roc_nix_sq_init(&eswitch_dev->nix, sq);
465 [ # # ]: 0 : if (rc)
466 : 0 : plt_err("Failed to init sq=%d, rc=%d", qid, rc);
467 : :
468 : 0 : eswitch_dev->txq[qid].state = CNXK_ESWITCH_QUEUE_STATE_CONFIGURED;
469 : :
470 : 0 : fail:
471 : 0 : return rc;
472 : : }
473 : :
474 : : static int
475 : 0 : nix_lf_setup(struct cnxk_eswitch_dev *eswitch_dev)
476 : : {
477 : : uint16_t nb_rxq, nb_txq, nb_cq;
478 : : struct roc_nix_fc_cfg fc_cfg;
479 : : struct roc_nix *nix;
480 : : uint64_t rx_cfg;
481 : : void *qs;
482 : : int rc;
483 : :
484 : : /* Initialize base roc nix */
485 : 0 : nix = &eswitch_dev->nix;
486 : 0 : nix->pci_dev = eswitch_dev->pci_dev;
487 : 0 : nix->hw_vlan_ins = true;
488 : 0 : nix->reta_sz = ROC_NIX_RSS_RETA_SZ_256;
489 : 0 : rc = roc_nix_dev_init(nix);
490 [ # # ]: 0 : if (rc) {
491 : 0 : plt_err("Failed to init nix eswitch device, rc=%d(%s)", rc, roc_error_msg_get(rc));
492 : 0 : goto fail;
493 : : }
494 : :
495 : : /* Get the representors count */
496 : 0 : rc = roc_nix_max_rep_count(&eswitch_dev->nix);
497 [ # # ]: 0 : if (rc) {
498 : 0 : plt_err("Failed to get rep cnt, rc=%d(%s)", rc, roc_error_msg_get(rc));
499 : 0 : goto free_cqs;
500 : : }
501 : 0 : eswitch_dev->repr_cnt.max_repr = eswitch_dev->nix.rep_cnt;
502 : :
503 : : /* Allocating an NIX LF */
504 : : nb_rxq = CNXK_ESWITCH_MAX_RXQ;
505 : : nb_txq = CNXK_ESWITCH_MAX_TXQ;
506 : : nb_cq = CNXK_ESWITCH_MAX_RXQ;
507 : : rx_cfg = ROC_NIX_LF_RX_CFG_DIS_APAD;
508 : 0 : rc = roc_nix_lf_alloc(nix, nb_rxq, nb_txq, rx_cfg);
509 [ # # ]: 0 : if (rc) {
510 : 0 : plt_err("lf alloc failed = %s(%d)", roc_error_msg_get(rc), rc);
511 : 0 : goto dev_fini;
512 : : }
513 : :
514 : : if (nb_rxq) {
515 : : /* Allocate memory for eswitch rq's and cq's */
516 : 0 : qs = plt_zmalloc(sizeof(struct cnxk_eswitch_rxq) * nb_rxq, 0);
517 [ # # ]: 0 : if (!qs) {
518 : 0 : plt_err("Failed to alloc eswitch rxq");
519 : 0 : goto lf_free;
520 : : }
521 : 0 : eswitch_dev->rxq = qs;
522 : : }
523 : :
524 : : if (nb_txq) {
525 : : /* Allocate memory for roc sq's */
526 : 0 : qs = plt_zmalloc(sizeof(struct cnxk_eswitch_txq) * nb_txq, 0);
527 [ # # ]: 0 : if (!qs) {
528 : 0 : plt_err("Failed to alloc eswitch txq");
529 : 0 : goto free_rqs;
530 : : }
531 : 0 : eswitch_dev->txq = qs;
532 : : }
533 : :
534 : : if (nb_cq) {
535 : 0 : qs = plt_zmalloc(sizeof(struct cnxk_eswitch_cxq) * nb_cq, 0);
536 [ # # ]: 0 : if (!qs) {
537 : 0 : plt_err("Failed to alloc eswitch cxq");
538 : 0 : goto free_sqs;
539 : : }
540 : 0 : eswitch_dev->cxq = qs;
541 : : }
542 : :
543 : 0 : eswitch_dev->nb_rxq = nb_rxq;
544 : 0 : eswitch_dev->nb_txq = nb_txq;
545 : :
546 : : /* Re-enable NIX LF error interrupts */
547 : 0 : roc_nix_err_intr_ena_dis(nix, true);
548 : 0 : roc_nix_ras_intr_ena_dis(nix, true);
549 : :
550 : 0 : rc = roc_nix_lso_fmt_setup(nix);
551 [ # # ]: 0 : if (rc) {
552 : 0 : plt_err("lso setup failed = %s(%d)", roc_error_msg_get(rc), rc);
553 : 0 : goto free_cqs;
554 : : }
555 : :
556 : 0 : rc = roc_nix_switch_hdr_set(nix, 0, 0, 0, 0);
557 [ # # ]: 0 : if (rc) {
558 : 0 : plt_err("switch hdr set failed = %s(%d)", roc_error_msg_get(rc), rc);
559 : 0 : goto free_cqs;
560 : : }
561 : :
562 : 0 : rc = roc_nix_tm_init(nix);
563 [ # # ]: 0 : if (rc) {
564 : 0 : plt_err("tm failed = %s(%d)", roc_error_msg_get(rc), rc);
565 : 0 : goto free_cqs;
566 : : }
567 : :
568 : : /* Register queue IRQs */
569 : 0 : rc = roc_nix_register_queue_irqs(nix);
570 [ # # ]: 0 : if (rc) {
571 : 0 : plt_err("Failed to register queue interrupts rc=%d", rc);
572 : 0 : goto tm_fini;
573 : : }
574 : :
575 : : /* Enable default tree */
576 : 0 : rc = roc_nix_tm_hierarchy_enable(nix, ROC_NIX_TM_DEFAULT, false);
577 [ # # ]: 0 : if (rc) {
578 : 0 : plt_err("tm default hierarchy enable failed = %s(%d)", roc_error_msg_get(rc), rc);
579 : 0 : goto q_irq_fini;
580 : : }
581 : :
582 : : memset(&fc_cfg, 0, sizeof(struct roc_nix_fc_cfg));
583 : : fc_cfg.rxchan_cfg.enable = false;
584 : 0 : rc = roc_nix_fc_config_set(nix, &fc_cfg);
585 [ # # ]: 0 : if (rc) {
586 : 0 : plt_err("Failed to setup flow control, rc=%d(%s)", rc, roc_error_msg_get(rc));
587 : 0 : goto q_irq_fini;
588 : : }
589 : :
590 : 0 : roc_nix_fc_mode_get(nix);
591 : :
592 : 0 : return rc;
593 : 0 : q_irq_fini:
594 : 0 : roc_nix_unregister_queue_irqs(nix);
595 : 0 : tm_fini:
596 : 0 : roc_nix_tm_fini(nix);
597 : 0 : free_cqs:
598 : 0 : rte_free(eswitch_dev->cxq);
599 : 0 : free_sqs:
600 : 0 : rte_free(eswitch_dev->txq);
601 : 0 : free_rqs:
602 : 0 : rte_free(eswitch_dev->rxq);
603 : 0 : lf_free:
604 : 0 : roc_nix_lf_free(nix);
605 : 0 : dev_fini:
606 : 0 : roc_nix_dev_fini(nix);
607 : : fail:
608 : : return rc;
609 : : }
610 : :
611 : : static int
612 : 0 : eswitch_hw_rsrc_setup(struct cnxk_eswitch_dev *eswitch_dev, struct rte_pci_device *pci_dev)
613 : : {
614 : : struct roc_nix *nix;
615 : : int rc;
616 : :
617 : 0 : nix = &eswitch_dev->nix;
618 : 0 : rc = nix_lf_setup(eswitch_dev);
619 [ # # ]: 0 : if (rc) {
620 : 0 : plt_err("Failed to setup hw rsrc, rc=%d(%s)", rc, roc_error_msg_get(rc));
621 : 0 : goto fail;
622 : : }
623 : :
624 : : /* Initialize roc npc */
625 : 0 : eswitch_dev->npc.roc_nix = nix;
626 : 0 : eswitch_dev->npc.flow_max_priority = 3;
627 : 0 : eswitch_dev->npc.flow_prealloc_size = 1;
628 : 0 : rc = roc_npc_init(&eswitch_dev->npc);
629 [ # # ]: 0 : if (rc)
630 : 0 : goto rsrc_cleanup;
631 : :
632 : : /* List for eswitch default flows */
633 : 0 : TAILQ_INIT(&eswitch_dev->esw_flow_list);
634 : :
635 : 0 : return rc;
636 : : rsrc_cleanup:
637 : 0 : eswitch_hw_rsrc_cleanup(eswitch_dev, pci_dev);
638 : : fail:
639 : : return rc;
640 : : }
641 : :
642 : : int
643 : 0 : cnxk_eswitch_representor_info_get(struct cnxk_eswitch_dev *eswitch_dev,
644 : : struct rte_eth_representor_info *info)
645 : : {
646 : : struct cnxk_eswitch_devargs *esw_da;
647 : : int rc = 0, n_entries, i, j = 0, k = 0;
648 : :
649 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_esw_da; i++) {
650 [ # # ]: 0 : for (j = 0; j < eswitch_dev->esw_da[i].nb_repr_ports; j++)
651 : 0 : k++;
652 : : }
653 : : n_entries = k;
654 : :
655 [ # # ]: 0 : if (info == NULL)
656 : 0 : goto out;
657 : :
658 : : if ((uint32_t)n_entries > info->nb_ranges_alloc)
659 : : n_entries = info->nb_ranges_alloc;
660 : :
661 : : k = 0;
662 : 0 : info->controller = 0;
663 : 0 : info->pf = 0;
664 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_esw_da; i++) {
665 : : esw_da = &eswitch_dev->esw_da[i];
666 : 0 : info->ranges[k].type = esw_da->da.type;
667 [ # # # ]: 0 : switch (esw_da->da.type) {
668 : 0 : case RTE_ETH_REPRESENTOR_PF:
669 : 0 : info->ranges[k].controller = 0;
670 : 0 : info->ranges[k].pf = esw_da->repr_hw_info[0].pfvf;
671 : 0 : info->ranges[k].vf = 0;
672 : 0 : info->ranges[k].id_base = info->ranges[i].pf;
673 : 0 : info->ranges[k].id_end = info->ranges[i].pf;
674 : 0 : snprintf(info->ranges[k].name, sizeof(info->ranges[k].name), "pf%d",
675 : : info->ranges[k].pf);
676 : 0 : k++;
677 : 0 : break;
678 : : case RTE_ETH_REPRESENTOR_VF:
679 [ # # ]: 0 : for (j = 0; j < esw_da->nb_repr_ports; j++) {
680 : 0 : info->ranges[k].controller = 0;
681 : 0 : info->ranges[k].pf = esw_da->da.ports[0];
682 : 0 : info->ranges[k].vf = esw_da->repr_hw_info[j].pfvf;
683 : 0 : info->ranges[k].id_base = esw_da->repr_hw_info[j].port_id;
684 : 0 : info->ranges[k].id_end = esw_da->repr_hw_info[j].port_id;
685 : 0 : snprintf(info->ranges[k].name, sizeof(info->ranges[k].name),
686 : : "pf%dvf%d", info->ranges[k].pf, info->ranges[k].vf);
687 : 0 : k++;
688 : : }
689 : : break;
690 : 0 : default:
691 : 0 : plt_err("Invalid type %d", esw_da->da.type);
692 : : rc = 0;
693 : 0 : goto fail;
694 : : };
695 : : }
696 : 0 : info->nb_ranges = k;
697 : : fail:
698 : : return rc;
699 : : out:
700 : 0 : return n_entries;
701 : : }
702 : :
703 : : static int
704 : 0 : cnxk_eswitch_dev_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
705 : : {
706 : : struct cnxk_eswitch_dev *eswitch_dev;
707 : : const struct rte_memzone *mz = NULL;
708 : : uint16_t num_reps;
709 : : int rc = -ENOMEM;
710 : :
711 : : RTE_SET_USED(pci_drv);
712 : :
713 : : eswitch_dev = cnxk_eswitch_pmd_priv();
714 [ # # ]: 0 : if (!eswitch_dev) {
715 : 0 : rc = roc_plt_init();
716 [ # # ]: 0 : if (rc) {
717 : 0 : plt_err("Failed to initialize platform model, rc=%d", rc);
718 : 0 : return rc;
719 : : }
720 : :
721 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
722 : : return 0;
723 : :
724 : 0 : mz = rte_memzone_reserve_aligned(CNXK_REP_ESWITCH_DEV_MZ, sizeof(*eswitch_dev),
725 : : SOCKET_ID_ANY, 0, RTE_CACHE_LINE_SIZE);
726 [ # # ]: 0 : if (mz == NULL) {
727 : 0 : plt_err("Failed to reserve a memzone");
728 : 0 : goto fail;
729 : : }
730 : :
731 : 0 : eswitch_dev = mz->addr;
732 : 0 : eswitch_dev->pci_dev = pci_dev;
733 : :
734 : 0 : rc = eswitch_hw_rsrc_setup(eswitch_dev, pci_dev);
735 [ # # ]: 0 : if (rc) {
736 : 0 : plt_err("Failed to setup hw rsrc, rc=%d(%s)", rc, roc_error_msg_get(rc));
737 : 0 : goto free_mem;
738 : : }
739 : : }
740 : :
741 [ # # ]: 0 : if (pci_dev->device.devargs) {
742 : 0 : rc = cnxk_eswitch_repr_devargs(pci_dev, eswitch_dev);
743 [ # # ]: 0 : if (rc)
744 : 0 : goto rsrc_cleanup;
745 : : }
746 : :
747 [ # # ]: 0 : if (eswitch_dev->repr_cnt.nb_repr_created > eswitch_dev->repr_cnt.max_repr) {
748 : 0 : plt_err("Representors to be created %d can be greater than max allowed %d",
749 : : eswitch_dev->repr_cnt.nb_repr_created, eswitch_dev->repr_cnt.max_repr);
750 : : rc = -EINVAL;
751 : 0 : goto rsrc_cleanup;
752 : : }
753 : :
754 : : num_reps = eswitch_dev->repr_cnt.nb_repr_created;
755 [ # # ]: 0 : if (!num_reps) {
756 : 0 : plt_err("No representors enabled");
757 : 0 : goto fail;
758 : : }
759 : :
760 : 0 : plt_esw_dbg("Max no of reps %d reps to be created %d Eswtch pfunc %x",
761 : : eswitch_dev->repr_cnt.max_repr, eswitch_dev->repr_cnt.nb_repr_created,
762 : : roc_nix_get_pf_func(&eswitch_dev->nix));
763 : :
764 : : /* Probe representor ports */
765 : 0 : rc = cnxk_rep_dev_probe(pci_dev, eswitch_dev);
766 [ # # ]: 0 : if (rc) {
767 : 0 : plt_err("Failed to probe representor ports");
768 : 0 : goto rsrc_cleanup;
769 : : }
770 : :
771 : : /* Spinlock for synchronization between representors traffic and control
772 : : * messages
773 : : */
774 : : rte_spinlock_init(&eswitch_dev->rep_lock);
775 : :
776 : 0 : return rc;
777 : 0 : rsrc_cleanup:
778 : 0 : eswitch_hw_rsrc_cleanup(eswitch_dev, pci_dev);
779 : 0 : free_mem:
780 : 0 : rte_memzone_free(mz);
781 : : fail:
782 : : return rc;
783 : : }
784 : :
785 : : static const struct rte_pci_id cnxk_eswitch_pci_map[] = {
786 : : {RTE_PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, PCI_DEVID_CNXK_RVU_ESWITCH_PF)},
787 : : {
788 : : .vendor_id = 0,
789 : : },
790 : : };
791 : :
792 : : static struct rte_pci_driver cnxk_eswitch_pci = {
793 : : .id_table = cnxk_eswitch_pci_map,
794 : : .drv_flags =
795 : : RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_NEED_IOVA_AS_VA | RTE_PCI_DRV_PROBE_AGAIN,
796 : : .probe = cnxk_eswitch_dev_probe,
797 : : .remove = cnxk_eswitch_dev_remove,
798 : : };
799 : :
800 : 276 : RTE_PMD_REGISTER_PCI(cnxk_eswitch, cnxk_eswitch_pci);
801 : : RTE_PMD_REGISTER_PCI_TABLE(cnxk_eswitch, cnxk_eswitch_pci_map);
802 : : RTE_PMD_REGISTER_KMOD_DEP(cnxk_eswitch, "vfio-pci");
|