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