Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(C) 2024 Marvell.
3 : : */
4 : : #include <cnxk_rep.h>
5 : : #include <cnxk_rep_msg.h>
6 : :
7 : : #define REPTE_MSG_PROC_THRD_NAME_MAX_LEN 30
8 : :
9 : : #define PF_SHIFT 10
10 : : #define PF_MASK 0x3F
11 : :
12 : : static uint16_t
13 : : get_pf(uint16_t hw_func)
14 : : {
15 : 0 : return (hw_func >> PF_SHIFT) & PF_MASK;
16 : : }
17 : :
18 : : static uint16_t
19 : : switch_domain_id_allocate(struct cnxk_eswitch_dev *eswitch_dev, uint16_t pf)
20 : : {
21 : : int i = 0;
22 : :
23 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_switch_domain; i++) {
24 [ # # ]: 0 : if (eswitch_dev->sw_dom[i].pf == pf)
25 : 0 : return eswitch_dev->sw_dom[i].switch_domain_id;
26 : : }
27 : :
28 : : return RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
29 : : }
30 : :
31 : : int
32 : 0 : cnxk_rep_state_update(struct cnxk_eswitch_dev *eswitch_dev, uint32_t state, uint16_t *rep_id)
33 : : {
34 : : struct cnxk_rep_dev *rep_dev = NULL;
35 : : struct rte_eth_dev *rep_eth_dev;
36 : : uint16_t hw_func, nb_rxq;
37 : : int i, rc = 0;
38 : :
39 : 0 : nb_rxq = state & 0xFFFF;
40 : 0 : hw_func = (state >> 16) & 0xFFFF;
41 : : /* Delete the individual PFVF flows as common eswitch VF rule will be used. */
42 : 0 : rc = cnxk_eswitch_flow_rules_delete(eswitch_dev, hw_func);
43 [ # # ]: 0 : if (rc) {
44 [ # # ]: 0 : if (rc != -ENOENT) {
45 : 0 : plt_err("Failed to delete %x flow rules", hw_func);
46 : 0 : goto fail;
47 : : }
48 : : }
49 : : /* Rep ID for respective HW func */
50 : 0 : rc = cnxk_eswitch_representor_id(eswitch_dev, hw_func, rep_id);
51 [ # # ]: 0 : if (rc) {
52 [ # # ]: 0 : if (rc != -ENOENT) {
53 : 0 : plt_err("Failed to get rep info for %x", hw_func);
54 : 0 : goto fail;
55 : : }
56 : : }
57 : : /* Update the state - representee is standalone or part of companian app */
58 [ # # ]: 0 : for (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {
59 : 0 : rep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;
60 [ # # ]: 0 : if (!rep_eth_dev) {
61 : 0 : plt_err("Failed to get rep ethdev handle");
62 : : rc = -EINVAL;
63 : 0 : goto fail;
64 : : }
65 : :
66 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
67 [ # # # # ]: 0 : if (rep_dev->hw_func == hw_func && rep_dev->is_vf_active) {
68 : 0 : rep_dev->native_repte = false;
69 : 0 : rep_dev->nb_rxq = nb_rxq;
70 : : }
71 : : }
72 : :
73 : : return 0;
74 : : fail:
75 : : return rc;
76 : : }
77 : :
78 : : int
79 : 0 : cnxk_rep_dev_uninit(struct rte_eth_dev *ethdev)
80 : : {
81 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev);
82 : :
83 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY)
84 : : return 0;
85 : :
86 : 0 : plt_rep_dbg("Representor port:%d uninit", ethdev->data->port_id);
87 : 0 : rte_free(ethdev->data->mac_addrs);
88 : 0 : ethdev->data->mac_addrs = NULL;
89 : :
90 : 0 : rep_dev->parent_dev->repr_cnt.nb_repr_probed--;
91 : :
92 : 0 : return 0;
93 : : }
94 : :
95 : : int
96 : 0 : cnxk_rep_dev_remove(struct cnxk_eswitch_dev *eswitch_dev)
97 : : {
98 : : int i, rc = 0;
99 : :
100 : 0 : roc_eswitch_nix_process_repte_notify_cb_unregister(&eswitch_dev->nix);
101 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_switch_domain; i++) {
102 : 0 : rc = rte_eth_switch_domain_free(eswitch_dev->sw_dom[i].switch_domain_id);
103 [ # # ]: 0 : if (rc)
104 : 0 : plt_err("Failed to alloc switch domain: %d", rc);
105 : : }
106 : :
107 : 0 : return rc;
108 : : }
109 : :
110 : : static int
111 : 0 : cnxk_representee_release(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func)
112 : : {
113 : : struct cnxk_rep_dev *rep_dev = NULL;
114 : : struct rte_eth_dev *rep_eth_dev;
115 : : int i, rc = 0;
116 : :
117 [ # # ]: 0 : for (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {
118 : 0 : rep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;
119 [ # # ]: 0 : if (!rep_eth_dev) {
120 : 0 : plt_err("Failed to get rep ethdev handle");
121 : : rc = -EINVAL;
122 : 0 : goto done;
123 : : }
124 : :
125 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
126 [ # # ]: 0 : if (rep_dev->hw_func == hw_func &&
127 [ # # # # ]: 0 : (!rep_dev->native_repte || rep_dev->is_vf_active)) {
128 : 0 : rep_dev->is_vf_active = false;
129 : 0 : rc = cnxk_rep_dev_stop(rep_eth_dev);
130 [ # # ]: 0 : if (rc) {
131 : 0 : plt_err("Failed to stop repr port %d, rep id %d", rep_dev->port_id,
132 : : rep_dev->rep_id);
133 : 0 : goto done;
134 : : }
135 : :
136 : 0 : cnxk_rep_rx_queue_release(rep_eth_dev, 0);
137 : 0 : cnxk_rep_tx_queue_release(rep_eth_dev, 0);
138 : 0 : plt_rep_dbg("Released representor ID %d representing %x", rep_dev->rep_id,
139 : : hw_func);
140 : 0 : break;
141 : : }
142 : : }
143 : 0 : done:
144 : 0 : return rc;
145 : : }
146 : :
147 : : static int
148 : 0 : cnxk_representee_setup(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func, uint16_t rep_id)
149 : : {
150 : : struct cnxk_rep_dev *rep_dev = NULL;
151 : : struct rte_eth_dev *rep_eth_dev;
152 : : int i, rc = 0;
153 : :
154 [ # # ]: 0 : for (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {
155 : 0 : rep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;
156 [ # # ]: 0 : if (!rep_eth_dev) {
157 : 0 : plt_err("Failed to get rep ethdev handle");
158 : : rc = -EINVAL;
159 : 0 : goto done;
160 : : }
161 : :
162 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
163 [ # # # # ]: 0 : if (rep_dev->hw_func == hw_func && !rep_dev->is_vf_active) {
164 : 0 : rep_dev->is_vf_active = true;
165 : 0 : rep_dev->native_repte = true;
166 [ # # ]: 0 : if (rep_dev->rep_id != rep_id) {
167 : 0 : plt_err("Rep ID assigned during init %d does not match %d",
168 : : rep_dev->rep_id, rep_id);
169 : : rc = -EINVAL;
170 : 0 : goto done;
171 : : }
172 : :
173 : 0 : rc = cnxk_rep_rx_queue_setup(rep_eth_dev, rep_dev->rxq->qid,
174 : 0 : rep_dev->rxq->nb_desc, 0,
175 : 0 : rep_dev->rxq->rx_conf, rep_dev->rxq->mpool);
176 [ # # ]: 0 : if (rc) {
177 : 0 : plt_err("Failed to setup rxq repr port %d, rep id %d",
178 : : rep_dev->port_id, rep_dev->rep_id);
179 : 0 : goto done;
180 : : }
181 : :
182 : 0 : rc = cnxk_rep_tx_queue_setup(rep_eth_dev, rep_dev->txq->qid,
183 : 0 : rep_dev->txq->nb_desc, 0,
184 : 0 : rep_dev->txq->tx_conf);
185 [ # # ]: 0 : if (rc) {
186 : 0 : plt_err("Failed to setup txq repr port %d, rep id %d",
187 : : rep_dev->port_id, rep_dev->rep_id);
188 : 0 : goto done;
189 : : }
190 : :
191 : 0 : rc = cnxk_rep_dev_start(rep_eth_dev);
192 [ # # ]: 0 : if (rc) {
193 : 0 : plt_err("Failed to start repr port %d, rep id %d", rep_dev->port_id,
194 : : rep_dev->rep_id);
195 : 0 : goto done;
196 : : }
197 : : break;
198 : : }
199 : : }
200 : 0 : done:
201 : 0 : return rc;
202 : : }
203 : :
204 : : static int
205 : 0 : cnxk_representee_state_msg_process(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func,
206 : : bool enable)
207 : : {
208 : : struct cnxk_eswitch_devargs *esw_da;
209 : : uint16_t rep_id = UINT16_MAX;
210 : : int rc = 0, i, j;
211 : :
212 : : /* Traversing the initialized represented list */
213 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_esw_da; i++) {
214 : : esw_da = &eswitch_dev->esw_da[i];
215 [ # # ]: 0 : for (j = 0; j < esw_da->nb_repr_ports; j++) {
216 [ # # ]: 0 : if (esw_da->repr_hw_info[j].hw_func == hw_func) {
217 : 0 : rep_id = esw_da->repr_hw_info[j].rep_id;
218 : 0 : break;
219 : : }
220 : : }
221 [ # # ]: 0 : if (rep_id != UINT16_MAX)
222 : : break;
223 : : }
224 : : /* No action on PF func for which representor has not been created */
225 [ # # ]: 0 : if (rep_id == UINT16_MAX)
226 : 0 : goto done;
227 : :
228 [ # # ]: 0 : if (enable) {
229 : 0 : rc = cnxk_representee_setup(eswitch_dev, hw_func, rep_id);
230 [ # # ]: 0 : if (rc) {
231 : 0 : plt_err("Failed to setup representee, err %d", rc);
232 : 0 : goto fail;
233 : : }
234 : 0 : plt_rep_dbg(" Representor ID %d representing %x", rep_id, hw_func);
235 : 0 : rc = cnxk_eswitch_flow_rules_install(eswitch_dev, hw_func);
236 [ # # ]: 0 : if (rc) {
237 : 0 : plt_err("Failed to install rxtx flow rules for %x", hw_func);
238 : 0 : goto fail;
239 : : }
240 : : } else {
241 : 0 : rc = cnxk_eswitch_flow_rules_delete(eswitch_dev, hw_func);
242 [ # # ]: 0 : if (rc) {
243 : 0 : plt_err("Failed to delete flow rules for %x", hw_func);
244 : 0 : goto fail;
245 : : }
246 : 0 : rc = cnxk_representee_release(eswitch_dev, hw_func);
247 [ # # ]: 0 : if (rc) {
248 : 0 : plt_err("Failed to release representee, err %d", rc);
249 : 0 : goto fail;
250 : : }
251 : : }
252 : :
253 : 0 : done:
254 : : return 0;
255 : : fail:
256 : : return rc;
257 : : }
258 : :
259 : : static int
260 : 0 : cnxk_representee_mtu_msg_process(struct cnxk_eswitch_dev *eswitch_dev, uint16_t hw_func,
261 : : uint16_t mtu)
262 : : {
263 : : struct cnxk_eswitch_devargs *esw_da;
264 : : struct cnxk_rep_dev *rep_dev = NULL;
265 : : struct rte_eth_dev *rep_eth_dev;
266 : : uint16_t rep_id = UINT16_MAX;
267 : : int rc = 0;
268 : : int i, j;
269 : :
270 : : /* Traversing the initialized represented list */
271 [ # # ]: 0 : for (i = 0; i < eswitch_dev->nb_esw_da; i++) {
272 : : esw_da = &eswitch_dev->esw_da[i];
273 [ # # ]: 0 : for (j = 0; j < esw_da->nb_repr_ports; j++) {
274 [ # # ]: 0 : if (esw_da->repr_hw_info[j].hw_func == hw_func) {
275 : 0 : rep_id = esw_da->repr_hw_info[j].rep_id;
276 : 0 : break;
277 : : }
278 : : }
279 [ # # ]: 0 : if (rep_id != UINT16_MAX)
280 : : break;
281 : : }
282 : : /* No action on PF func for which representor has not been created */
283 [ # # ]: 0 : if (rep_id == UINT16_MAX)
284 : 0 : goto done;
285 : :
286 [ # # ]: 0 : for (i = 0; i < eswitch_dev->repr_cnt.nb_repr_probed; i++) {
287 : 0 : rep_eth_dev = eswitch_dev->rep_info[i].rep_eth_dev;
288 [ # # ]: 0 : if (!rep_eth_dev) {
289 : 0 : plt_err("Failed to get rep ethdev handle");
290 : : rc = -EINVAL;
291 : 0 : goto done;
292 : : }
293 : :
294 : : rep_dev = cnxk_rep_pmd_priv(rep_eth_dev);
295 [ # # ]: 0 : if (rep_dev->rep_id == rep_id) {
296 : 0 : plt_rep_dbg("Setting MTU as %d for hw_func %x rep_id %d", mtu, hw_func,
297 : : rep_id);
298 : 0 : rep_dev->repte_mtu = mtu;
299 : 0 : break;
300 : : }
301 : : }
302 : :
303 : 0 : done:
304 : 0 : return rc;
305 : : }
306 : :
307 : : static int
308 : 0 : cnxk_representee_msg_process(struct cnxk_eswitch_dev *eswitch_dev,
309 : : struct roc_eswitch_repte_notify_msg *notify_msg)
310 : : {
311 : : int rc = 0;
312 : :
313 [ # # # # ]: 0 : switch (notify_msg->type) {
314 : 0 : case ROC_ESWITCH_REPTE_STATE:
315 [ # # ]: 0 : plt_rep_dbg(" REPTE STATE: hw_func %x action %s", notify_msg->state.hw_func,
316 : : notify_msg->state.enable ? "enable" : "disable");
317 : 0 : rc = cnxk_representee_state_msg_process(eswitch_dev, notify_msg->state.hw_func,
318 : 0 : notify_msg->state.enable);
319 : 0 : break;
320 : 0 : case ROC_ESWITCH_LINK_STATE:
321 [ # # ]: 0 : plt_rep_dbg(" LINK STATE: hw_func %x action %s", notify_msg->link.hw_func,
322 : : notify_msg->link.enable ? "enable" : "disable");
323 : 0 : break;
324 : 0 : case ROC_ESWITCH_REPTE_MTU:
325 : 0 : plt_rep_dbg(" REPTE MTU: hw_func %x rep_id %d mtu %d", notify_msg->mtu.hw_func,
326 : : notify_msg->mtu.rep_id, notify_msg->mtu.mtu);
327 : 0 : rc = cnxk_representee_mtu_msg_process(eswitch_dev, notify_msg->mtu.hw_func,
328 : 0 : notify_msg->mtu.mtu);
329 : 0 : break;
330 : 0 : default:
331 : 0 : plt_err("Invalid notification msg received %d", notify_msg->type);
332 : 0 : break;
333 : : };
334 : :
335 : 0 : return rc;
336 : : }
337 : :
338 : : static uint32_t
339 : 0 : cnxk_representee_msg_thread_main(void *arg)
340 : : {
341 : : struct cnxk_eswitch_dev *eswitch_dev = (struct cnxk_eswitch_dev *)arg;
342 : : struct cnxk_esw_repte_msg_proc *repte_msg_proc;
343 : : struct cnxk_esw_repte_msg *msg, *next_msg;
344 : : int count, rc;
345 : :
346 : : repte_msg_proc = &eswitch_dev->repte_msg_proc;
347 : 0 : pthread_mutex_lock(&eswitch_dev->repte_msg_proc.mutex);
348 [ # # ]: 0 : while (eswitch_dev->repte_msg_proc.start_thread) {
349 : : do {
350 : 0 : rc = pthread_cond_wait(&eswitch_dev->repte_msg_proc.repte_msg_cond,
351 : : &eswitch_dev->repte_msg_proc.mutex);
352 [ # # ]: 0 : } while (rc != 0);
353 : :
354 : : /* Go through list pushed from interrupt context and process each message */
355 : 0 : next_msg = TAILQ_FIRST(&repte_msg_proc->msg_list);
356 : : count = 0;
357 [ # # ]: 0 : while (next_msg) {
358 : : msg = next_msg;
359 : 0 : count++;
360 : 0 : plt_rep_dbg(" Processing msg %d: ", count);
361 : : /* Unlocking for interrupt thread to grab lock
362 : : * while thread process the message.
363 : : */
364 : 0 : pthread_mutex_unlock(&eswitch_dev->repte_msg_proc.mutex);
365 : : /* Processing the message */
366 : 0 : cnxk_representee_msg_process(eswitch_dev, msg->notify_msg);
367 : : /* Locking as cond wait will unlock before wait */
368 : 0 : pthread_mutex_lock(&eswitch_dev->repte_msg_proc.mutex);
369 : 0 : next_msg = TAILQ_NEXT(msg, next);
370 [ # # ]: 0 : TAILQ_REMOVE(&repte_msg_proc->msg_list, msg, next);
371 : 0 : rte_free(msg->notify_msg);
372 : 0 : rte_free(msg);
373 : : }
374 : : }
375 : :
376 : 0 : pthread_mutex_unlock(&eswitch_dev->repte_msg_proc.mutex);
377 : :
378 : 0 : return 0;
379 : : }
380 : :
381 : : static int
382 : 0 : cnxk_representee_notification(void *roc_nix, struct roc_eswitch_repte_notify_msg *notify_msg)
383 : : {
384 : : struct cnxk_esw_repte_msg_proc *repte_msg_proc;
385 : : struct cnxk_eswitch_dev *eswitch_dev;
386 : : struct cnxk_esw_repte_msg *msg;
387 : : int rc = 0;
388 : :
389 : : RTE_SET_USED(roc_nix);
390 : : eswitch_dev = cnxk_eswitch_pmd_priv();
391 [ # # ]: 0 : if (!eswitch_dev) {
392 : 0 : plt_err("Failed to get PF ethdev handle");
393 : : rc = -EINVAL;
394 : 0 : goto done;
395 : : }
396 : :
397 : : repte_msg_proc = &eswitch_dev->repte_msg_proc;
398 : 0 : msg = rte_zmalloc("msg", sizeof(struct cnxk_esw_repte_msg), 0);
399 [ # # ]: 0 : if (!msg) {
400 : 0 : plt_err("Failed to allocate memory for repte msg");
401 : : rc = -ENOMEM;
402 : 0 : goto done;
403 : : }
404 : :
405 : 0 : msg->notify_msg = plt_zmalloc(sizeof(struct roc_eswitch_repte_notify_msg), 0);
406 [ # # ]: 0 : if (!msg->notify_msg) {
407 : 0 : plt_err("Failed to allocate memory");
408 : : rc = -ENOMEM;
409 : 0 : goto done;
410 : : }
411 : :
412 : : rte_memcpy(msg->notify_msg, notify_msg, sizeof(struct roc_eswitch_repte_notify_msg));
413 : 0 : plt_rep_dbg("Pushing new notification : msg type %d", msg->notify_msg->type);
414 : 0 : pthread_mutex_lock(&eswitch_dev->repte_msg_proc.mutex);
415 : 0 : TAILQ_INSERT_TAIL(&repte_msg_proc->msg_list, msg, next);
416 : : /* Signal vf message handler thread */
417 : 0 : pthread_cond_signal(&eswitch_dev->repte_msg_proc.repte_msg_cond);
418 : 0 : pthread_mutex_unlock(&eswitch_dev->repte_msg_proc.mutex);
419 : :
420 : 0 : done:
421 : 0 : return rc;
422 : : }
423 : :
424 : : static int
425 : 0 : cnxk_rep_parent_setup(struct cnxk_eswitch_dev *eswitch_dev)
426 : : {
427 : : uint16_t pf, prev_pf = 0, switch_domain_id;
428 : : int rc, i, j = 0;
429 : :
430 [ # # ]: 0 : if (eswitch_dev->rep_info)
431 : : return 0;
432 : :
433 : 0 : eswitch_dev->rep_info =
434 : 0 : plt_zmalloc(sizeof(eswitch_dev->rep_info[0]) * eswitch_dev->repr_cnt.max_repr, 0);
435 [ # # ]: 0 : if (!eswitch_dev->rep_info) {
436 : 0 : plt_err("Failed to alloc memory for rep info");
437 : : rc = -ENOMEM;
438 : 0 : goto fail;
439 : : }
440 : :
441 : : /* Allocate switch domain for all PFs (VFs will be under same domain as PF) */
442 [ # # ]: 0 : for (i = 0; i < eswitch_dev->repr_cnt.max_repr; i++) {
443 : 0 : pf = get_pf(eswitch_dev->nix.rep_pfvf_map[i]);
444 [ # # ]: 0 : if (pf == prev_pf)
445 : 0 : continue;
446 : :
447 : 0 : rc = rte_eth_switch_domain_alloc(&switch_domain_id);
448 [ # # ]: 0 : if (rc) {
449 : 0 : plt_err("Failed to alloc switch domain: %d", rc);
450 : 0 : goto fail;
451 : : }
452 : 0 : plt_rep_dbg("Allocated switch domain id %d for pf %d", switch_domain_id, pf);
453 : 0 : eswitch_dev->sw_dom[j].switch_domain_id = switch_domain_id;
454 : 0 : eswitch_dev->sw_dom[j].pf = pf;
455 : : prev_pf = pf;
456 : 0 : j++;
457 : : }
458 : 0 : eswitch_dev->nb_switch_domain = j;
459 : :
460 : 0 : return 0;
461 : : fail:
462 : : return rc;
463 : : }
464 : :
465 : : static int
466 : 0 : cnxk_rep_dev_init(struct rte_eth_dev *eth_dev, void *params)
467 : : {
468 : : struct cnxk_rep_dev *rep_params = (struct cnxk_rep_dev *)params;
469 : : struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev);
470 : :
471 : 0 : rep_dev->port_id = rep_params->port_id;
472 : 0 : rep_dev->switch_domain_id = rep_params->switch_domain_id;
473 : 0 : rep_dev->parent_dev = rep_params->parent_dev;
474 : 0 : rep_dev->hw_func = rep_params->hw_func;
475 : 0 : rep_dev->rep_id = rep_params->rep_id;
476 : :
477 : 0 : eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
478 : 0 : eth_dev->data->representor_id = rep_params->port_id;
479 : 0 : eth_dev->data->backer_port_id = eth_dev->data->port_id;
480 : :
481 : 0 : eth_dev->data->mac_addrs = plt_zmalloc(RTE_ETHER_ADDR_LEN, 0);
482 [ # # ]: 0 : if (!eth_dev->data->mac_addrs) {
483 : 0 : plt_err("Failed to allocate memory for mac addr");
484 : 0 : return -ENOMEM;
485 : : }
486 : :
487 : 0 : rte_eth_random_addr(rep_dev->mac_addr);
488 : 0 : memcpy(eth_dev->data->mac_addrs, rep_dev->mac_addr, RTE_ETHER_ADDR_LEN);
489 : :
490 : : /* Set the device operations */
491 : 0 : eth_dev->dev_ops = &cnxk_rep_dev_ops;
492 : :
493 : : /* Rx/Tx functions stubs to avoid crashing */
494 : 0 : eth_dev->rx_pkt_burst = cnxk_rep_rx_burst_dummy;
495 : 0 : eth_dev->tx_pkt_burst = cnxk_rep_tx_burst_dummy;
496 : :
497 : : /* Only single queues for representor devices */
498 : 0 : eth_dev->data->nb_rx_queues = 1;
499 : 0 : eth_dev->data->nb_tx_queues = 1;
500 : :
501 : 0 : eth_dev->data->dev_link.link_speed = RTE_ETH_SPEED_NUM_NONE;
502 : 0 : eth_dev->data->dev_link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
503 : 0 : eth_dev->data->dev_link.link_status = RTE_ETH_LINK_UP;
504 : 0 : eth_dev->data->dev_link.link_autoneg = RTE_ETH_LINK_FIXED;
505 : :
506 : 0 : return 0;
507 : : }
508 : :
509 : : static int
510 : 0 : create_representor_ethdev(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev,
511 : : struct cnxk_eswitch_devargs *esw_da, int idx)
512 : : {
513 : : char name[RTE_ETH_NAME_MAX_LEN];
514 : : struct rte_eth_dev *rep_eth_dev;
515 : : uint16_t hw_func;
516 : : int rc = 0;
517 : :
518 : 0 : struct cnxk_rep_dev rep = {.port_id = eswitch_dev->repr_cnt.nb_repr_probed,
519 : : .parent_dev = eswitch_dev};
520 : :
521 [ # # ]: 0 : if (esw_da->type == CNXK_ESW_DA_TYPE_PFVF) {
522 : 0 : hw_func = esw_da->repr_hw_info[idx].hw_func;
523 : 0 : rep.switch_domain_id = switch_domain_id_allocate(eswitch_dev, get_pf(hw_func));
524 [ # # ]: 0 : if (rep.switch_domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
525 : 0 : plt_err("Failed to get a valid switch domain id");
526 : : rc = -EINVAL;
527 : 0 : goto fail;
528 : : }
529 : :
530 : 0 : esw_da->repr_hw_info[idx].port_id = rep.port_id;
531 : : /* Representor port net_bdf_port */
532 : 0 : snprintf(name, sizeof(name), "net_%s_hw_%x_representor_%d", pci_dev->device.name,
533 : : hw_func, rep.port_id);
534 : :
535 : 0 : rep.hw_func = hw_func;
536 : 0 : rep.rep_id = esw_da->repr_hw_info[idx].rep_id;
537 : :
538 : : } else {
539 : 0 : snprintf(name, sizeof(name), "net_%s_representor_%d", pci_dev->device.name,
540 : : rep.port_id);
541 : 0 : rep.switch_domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
542 : : }
543 : :
544 : 0 : rc = rte_eth_dev_create(&pci_dev->device, name, sizeof(struct cnxk_rep_dev), NULL, NULL,
545 : : cnxk_rep_dev_init, &rep);
546 [ # # ]: 0 : if (rc) {
547 : 0 : plt_err("Failed to create cnxk vf representor %s", name);
548 : : rc = -EINVAL;
549 : 0 : goto fail;
550 : : }
551 : :
552 : 0 : rep_eth_dev = rte_eth_dev_allocated(name);
553 [ # # ]: 0 : if (!rep_eth_dev) {
554 : 0 : plt_err("Failed to find the eth_dev for VF-Rep: %s.", name);
555 : : rc = -ENODEV;
556 : 0 : goto fail;
557 : : }
558 : :
559 : 0 : plt_rep_dbg("Representor portid %d (%s) type %d probe done", rep_eth_dev->data->port_id,
560 : : name, esw_da->da.type);
561 : 0 : eswitch_dev->rep_info[rep.port_id].rep_eth_dev = rep_eth_dev;
562 : 0 : eswitch_dev->repr_cnt.nb_repr_probed++;
563 : :
564 : 0 : return 0;
565 : : fail:
566 : : return rc;
567 : : }
568 : :
569 : : int
570 : 0 : cnxk_rep_dev_probe(struct rte_pci_device *pci_dev, struct cnxk_eswitch_dev *eswitch_dev)
571 : : {
572 : : char name[REPTE_MSG_PROC_THRD_NAME_MAX_LEN];
573 : : struct cnxk_eswitch_devargs *esw_da;
574 : : uint16_t num_rep;
575 : : int i, j, rc;
576 : :
577 [ # # ]: 0 : if (eswitch_dev->repr_cnt.nb_repr_created > RTE_MAX_ETHPORTS) {
578 : 0 : plt_err("nb_representor_ports %d > %d MAX ETHPORTS",
579 : : eswitch_dev->repr_cnt.nb_repr_created, RTE_MAX_ETHPORTS);
580 : : rc = -EINVAL;
581 : 0 : goto fail;
582 : : }
583 : :
584 : : /* Initialize the internals of representor ports */
585 : 0 : rc = cnxk_rep_parent_setup(eswitch_dev);
586 [ # # ]: 0 : if (rc) {
587 : 0 : plt_err("Failed to setup the parent device, err %d", rc);
588 : 0 : goto fail;
589 : : }
590 : :
591 [ # # ]: 0 : for (i = eswitch_dev->last_probed; i < eswitch_dev->nb_esw_da; i++) {
592 : 0 : esw_da = &eswitch_dev->esw_da[i];
593 : : /* Check the representor devargs */
594 : 0 : num_rep = esw_da->nb_repr_ports;
595 [ # # ]: 0 : for (j = 0; j < num_rep; j++) {
596 : 0 : rc = create_representor_ethdev(pci_dev, eswitch_dev, esw_da, j);
597 [ # # ]: 0 : if (rc)
598 : 0 : goto fail;
599 : : }
600 : : }
601 : 0 : eswitch_dev->last_probed = i;
602 : :
603 : : /* Launch a thread to handle control messages */
604 [ # # ]: 0 : if (!eswitch_dev->start_ctrl_msg_thrd) {
605 : 0 : rc = cnxk_rep_msg_control_thread_launch(eswitch_dev);
606 [ # # ]: 0 : if (rc) {
607 : 0 : plt_err("Failed to launch message ctrl thread");
608 : 0 : goto fail;
609 : : }
610 : : }
611 : :
612 [ # # ]: 0 : if (!eswitch_dev->repte_msg_proc.start_thread) {
613 : : /* Register callback for representee notification */
614 [ # # ]: 0 : if (roc_eswitch_nix_process_repte_notify_cb_register(&eswitch_dev->nix,
615 : : cnxk_representee_notification)) {
616 : 0 : plt_err("Failed to register callback for representee notification");
617 : : rc = -EINVAL;
618 : 0 : goto fail;
619 : : }
620 : :
621 : : /* Create a thread for handling msgs from VFs */
622 : 0 : TAILQ_INIT(&eswitch_dev->repte_msg_proc.msg_list);
623 : 0 : pthread_cond_init(&eswitch_dev->repte_msg_proc.repte_msg_cond, NULL);
624 : 0 : pthread_mutex_init(&eswitch_dev->repte_msg_proc.mutex, NULL);
625 : :
626 : 0 : rte_strscpy(name, "repte_msg_proc_thrd", REPTE_MSG_PROC_THRD_NAME_MAX_LEN);
627 : 0 : eswitch_dev->repte_msg_proc.start_thread = true;
628 : : rc =
629 : 0 : rte_thread_create_internal_control(&eswitch_dev->repte_msg_proc.repte_msg_thread,
630 : : name, cnxk_representee_msg_thread_main,
631 : : eswitch_dev);
632 [ # # ]: 0 : if (rc != 0) {
633 : 0 : plt_err("Failed to create thread for VF mbox handling");
634 : 0 : goto thread_fail;
635 : : }
636 : : }
637 : :
638 : : return 0;
639 : : thread_fail:
640 : 0 : pthread_mutex_destroy(&eswitch_dev->repte_msg_proc.mutex);
641 : 0 : pthread_cond_destroy(&eswitch_dev->repte_msg_proc.repte_msg_cond);
642 : : fail:
643 : : return rc;
644 : : }
|