Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright(c) 2019-2021 Xilinx, Inc.
4 : : * Copyright(c) 2019 Solarflare Communications Inc.
5 : : *
6 : : * This software was jointly developed between OKTET Labs (under contract
7 : : * for Solarflare) and Solarflare Communications, Inc.
8 : : */
9 : :
10 : : #include <stdbool.h>
11 : :
12 : : #include <rte_common.h>
13 : : #include <rte_spinlock.h>
14 : :
15 : : #include "efx.h"
16 : :
17 : : #include "sfc.h"
18 : : #include "sfc_log.h"
19 : : #include "sfc_switch.h"
20 : :
21 : : /**
22 : : * Switch port registry entry.
23 : : *
24 : : * Drivers aware of RTE switch domains also have to maintain RTE switch
25 : : * port IDs for RTE ethdev instances they operate. These IDs are supposed
26 : : * to stand for physical interconnect entities, in example, PCIe functions.
27 : : *
28 : : * In terms of MAE, a physical interconnect entity can be referred to using
29 : : * an MPORT selector, that is, a 32-bit value. RTE switch port IDs, in turn,
30 : : * are 16-bit values, so indirect mapping has to be maintained:
31 : : *
32 : : * +--------------------+ +---------------------------------------+
33 : : * | RTE switch port ID | ------ | MAE switch port entry |
34 : : * +--------------------+ | --------------------- |
35 : : * | |
36 : : * | Entity (PCIe function) MPORT selector |
37 : : * | + |
38 : : * | Port type (independent/representor) |
39 : : * +---------------------------------------+
40 : : *
41 : : * This mapping comprises a port type to ensure that RTE switch port ID
42 : : * of a represented entity and that of its representor are different in
43 : : * the case when the entity gets plugged into DPDK and not into a guest.
44 : : *
45 : : * Entry data also comprises RTE ethdev's own MPORT. This value
46 : : * coincides with the entity MPORT in the case of independent ports.
47 : : * In the case of representors, this ID is not a selector and refers
48 : : * to an allocatable object (that is, it's likely to change on RTE
49 : : * ethdev replug). Flow API backend must use this value rather
50 : : * than entity_mport to support flow rule action PORT_ID.
51 : : */
52 : : struct sfc_mae_switch_port {
53 : : TAILQ_ENTRY(sfc_mae_switch_port) switch_domain_ports;
54 : :
55 : : /** RTE ethdev MPORT */
56 : : efx_mport_sel_t ethdev_mport;
57 : : /** RTE ethdev port ID */
58 : : uint16_t ethdev_port_id;
59 : :
60 : : /** Entity (PCIe function) MPORT selector */
61 : : efx_mport_sel_t entity_mport;
62 : : /** Port type (independent/representor) */
63 : : enum sfc_mae_switch_port_type type;
64 : : /** RTE switch port ID */
65 : : uint16_t id;
66 : :
67 : : union sfc_mae_switch_port_data data;
68 : : };
69 : :
70 : : TAILQ_HEAD(sfc_mae_switch_ports, sfc_mae_switch_port);
71 : :
72 : : /**
73 : : * Switch domain registry entry.
74 : : *
75 : : * Even if an RTE ethdev instance gets unplugged, the corresponding
76 : : * entry in the switch port registry will not be removed because the
77 : : * entity (PCIe function) MPORT is static and cannot change. If this
78 : : * RTE ethdev gets plugged back, the entry will be reused, and
79 : : * RTE switch port ID will be the same.
80 : : */
81 : : struct sfc_mae_switch_domain {
82 : : TAILQ_ENTRY(sfc_mae_switch_domain) entries;
83 : :
84 : : /** HW switch ID */
85 : : struct sfc_hw_switch_id *hw_switch_id;
86 : : /** The number of ports in the switch port registry */
87 : : unsigned int nb_ports;
88 : : /** Switch port registry */
89 : : struct sfc_mae_switch_ports ports;
90 : : /** RTE switch domain ID allocated for a group of devices */
91 : : uint16_t id;
92 : : /** DPDK controller -> EFX interface mapping */
93 : : efx_pcie_interface_t *controllers;
94 : : /** Number of DPDK controllers and EFX interfaces */
95 : : size_t nb_controllers;
96 : : /** MAE admin port */
97 : : struct sfc_mae_switch_port *mae_admin_port;
98 : : };
99 : :
100 : : TAILQ_HEAD(sfc_mae_switch_domains, sfc_mae_switch_domain);
101 : :
102 : : /**
103 : : * MAE representation of RTE switch infrastructure.
104 : : *
105 : : * It is possible that an RTE flow API client tries to insert a rule
106 : : * referencing an RTE ethdev deployed on top of a different physical
107 : : * device (it may belong to the same vendor or not). This particular
108 : : * driver/engine cannot support this and has to turn down such rules.
109 : : *
110 : : * Technically, it's HW switch identifier which, if queried for each
111 : : * RTE ethdev instance, indicates relationship between the instances.
112 : : * In the meantime, RTE flow API clients also need to somehow figure
113 : : * out relationship between RTE ethdev instances in advance.
114 : : *
115 : : * The concept of RTE switch domains resolves this issue. The driver
116 : : * maintains a static list of switch domains which is easy to browse,
117 : : * and each RTE ethdev fills RTE switch parameters in device
118 : : * information structure which is made available to clients.
119 : : *
120 : : * Even if all RTE ethdev instances belonging to a switch domain get
121 : : * unplugged, the corresponding entry in the switch domain registry
122 : : * will not be removed because the corresponding HW switch exists
123 : : * regardless of its ports being plugged to DPDK or kept aside.
124 : : * If a port gets plugged back to DPDK, the corresponding
125 : : * RTE ethdev will indicate the same RTE switch domain ID.
126 : : */
127 : : struct sfc_mae_switch {
128 : : /** A lock to protect the whole structure */
129 : : rte_spinlock_t lock;
130 : : /** Switch domain registry */
131 : : struct sfc_mae_switch_domains domains;
132 : : };
133 : :
134 : : static struct sfc_mae_switch sfc_mae_switch = {
135 : : .lock = RTE_SPINLOCK_INITIALIZER,
136 : : .domains = TAILQ_HEAD_INITIALIZER(sfc_mae_switch.domains),
137 : : };
138 : :
139 : :
140 : : /* This function expects to be called only when the lock is held */
141 : : static struct sfc_mae_switch_domain *
142 : : sfc_mae_find_switch_domain_by_id(uint16_t switch_domain_id)
143 : : {
144 : : struct sfc_mae_switch_domain *domain;
145 : :
146 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
147 : :
148 [ # # # # : 0 : TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) {
# # # # #
# # # # #
# # # # ]
149 [ # # # # : 0 : if (domain->id == switch_domain_id)
# # # # #
# # # # #
# # # # ]
150 : : return domain;
151 : : }
152 : :
153 : : return NULL;
154 : : }
155 : :
156 : : int
157 : 0 : sfc_mae_switch_ports_iterate(uint16_t switch_domain_id,
158 : : sfc_mae_switch_port_iterator_cb *cb,
159 : : void *data)
160 : : {
161 : : struct sfc_mae_switch_domain *domain;
162 : : struct sfc_mae_switch_port *port;
163 : :
164 [ # # ]: 0 : if (cb == NULL)
165 : : return EINVAL;
166 : :
167 : : rte_spinlock_lock(&sfc_mae_switch.lock);
168 : :
169 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
170 [ # # ]: 0 : if (domain == NULL) {
171 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
172 : 0 : return EINVAL;
173 : : }
174 : :
175 [ # # ]: 0 : TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
176 : 0 : cb(port->type, &port->ethdev_mport, port->ethdev_port_id,
177 : 0 : &port->entity_mport, port->id, &port->data, data);
178 : : }
179 : :
180 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
181 : 0 : return 0;
182 : : }
183 : :
184 : : /* This function expects to be called only when the lock is held */
185 : : static struct sfc_mae_switch_domain *
186 : 0 : sfc_mae_find_switch_domain_by_hw_switch_id(const struct sfc_hw_switch_id *id)
187 : : {
188 : : struct sfc_mae_switch_domain *domain;
189 : :
190 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
191 : :
192 [ # # ]: 0 : TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) {
193 [ # # ]: 0 : if (sfc_hw_switch_ids_equal(domain->hw_switch_id, id))
194 : 0 : return domain;
195 : : }
196 : :
197 : : return NULL;
198 : : }
199 : :
200 : : int
201 : 0 : sfc_mae_assign_switch_domain(struct sfc_adapter *sa,
202 : : uint16_t *switch_domain_id)
203 : : {
204 : : struct sfc_hw_switch_id *hw_switch_id;
205 : : struct sfc_mae_switch_domain *domain;
206 : : int rc;
207 : :
208 : : rte_spinlock_lock(&sfc_mae_switch.lock);
209 : :
210 : 0 : rc = sfc_hw_switch_id_init(sa, &hw_switch_id);
211 [ # # ]: 0 : if (rc != 0)
212 : 0 : goto fail_hw_switch_id_init;
213 : :
214 : 0 : domain = sfc_mae_find_switch_domain_by_hw_switch_id(hw_switch_id);
215 [ # # ]: 0 : if (domain != NULL) {
216 : 0 : sfc_hw_switch_id_fini(sa, hw_switch_id);
217 : 0 : goto done;
218 : : }
219 : :
220 : 0 : domain = rte_zmalloc("sfc_mae_switch_domain", sizeof(*domain), 0);
221 [ # # ]: 0 : if (domain == NULL) {
222 : : rc = ENOMEM;
223 : 0 : goto fail_mem_alloc;
224 : : }
225 : :
226 : : /*
227 : : * This code belongs to driver init path, that is, negation is
228 : : * done at the end of the path by sfc_eth_dev_init(). RTE APIs
229 : : * negate error codes, so drop negation here.
230 : : */
231 : 0 : rc = -rte_eth_switch_domain_alloc(&domain->id);
232 [ # # ]: 0 : if (rc != 0)
233 : 0 : goto fail_domain_alloc;
234 : :
235 : 0 : domain->hw_switch_id = hw_switch_id;
236 : :
237 : 0 : TAILQ_INIT(&domain->ports);
238 : :
239 : 0 : TAILQ_INSERT_TAIL(&sfc_mae_switch.domains, domain, entries);
240 : :
241 : 0 : done:
242 : 0 : *switch_domain_id = domain->id;
243 : :
244 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
245 : :
246 : 0 : return 0;
247 : :
248 : : fail_domain_alloc:
249 : 0 : rte_free(domain);
250 : :
251 : 0 : fail_mem_alloc:
252 : 0 : sfc_hw_switch_id_fini(sa, hw_switch_id);
253 : :
254 : 0 : fail_hw_switch_id_init:
255 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
256 : 0 : return rc;
257 : : }
258 : :
259 : : int
260 : 0 : sfc_mae_switch_domain_controllers(uint16_t switch_domain_id,
261 : : const efx_pcie_interface_t **controllers,
262 : : size_t *nb_controllers)
263 : : {
264 : : struct sfc_mae_switch_domain *domain;
265 : :
266 [ # # ]: 0 : if (controllers == NULL || nb_controllers == NULL)
267 : : return EINVAL;
268 : :
269 : : rte_spinlock_lock(&sfc_mae_switch.lock);
270 : :
271 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
272 [ # # ]: 0 : if (domain == NULL) {
273 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
274 : 0 : return EINVAL;
275 : : }
276 : :
277 : 0 : *controllers = domain->controllers;
278 : 0 : *nb_controllers = domain->nb_controllers;
279 : :
280 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
281 : 0 : return 0;
282 : : }
283 : :
284 : : int
285 : 0 : sfc_mae_switch_domain_map_controllers(uint16_t switch_domain_id,
286 : : efx_pcie_interface_t *controllers,
287 : : size_t nb_controllers)
288 : : {
289 : : struct sfc_mae_switch_domain *domain;
290 : :
291 : : rte_spinlock_lock(&sfc_mae_switch.lock);
292 : :
293 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
294 [ # # ]: 0 : if (domain == NULL) {
295 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
296 : 0 : return EINVAL;
297 : : }
298 : :
299 : : /* Controller mapping may be set only once */
300 [ # # ]: 0 : if (domain->controllers != NULL) {
301 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
302 : 0 : return EINVAL;
303 : : }
304 : :
305 : 0 : domain->controllers = controllers;
306 : 0 : domain->nb_controllers = nb_controllers;
307 : :
308 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
309 : 0 : return 0;
310 : : }
311 : :
312 : : int
313 : 0 : sfc_mae_switch_controller_from_mapping(const efx_pcie_interface_t *controllers,
314 : : size_t nb_controllers,
315 : : efx_pcie_interface_t intf,
316 : : int *controller)
317 : : {
318 : : size_t i;
319 : :
320 [ # # ]: 0 : if (controllers == NULL)
321 : : return ENOENT;
322 : :
323 [ # # ]: 0 : for (i = 0; i < nb_controllers; i++) {
324 [ # # ]: 0 : if (controllers[i] == intf) {
325 : 0 : *controller = i;
326 : 0 : return 0;
327 : : }
328 : : }
329 : :
330 : : return ENOENT;
331 : : }
332 : :
333 : : int
334 : 0 : sfc_mae_switch_domain_get_controller(uint16_t switch_domain_id,
335 : : efx_pcie_interface_t intf,
336 : : int *controller)
337 : : {
338 : : const efx_pcie_interface_t *controllers;
339 : : size_t nb_controllers;
340 : : int rc;
341 : :
342 : 0 : rc = sfc_mae_switch_domain_controllers(switch_domain_id, &controllers,
343 : : &nb_controllers);
344 [ # # ]: 0 : if (rc != 0)
345 : : return rc;
346 : :
347 : 0 : return sfc_mae_switch_controller_from_mapping(controllers,
348 : : nb_controllers,
349 : : intf,
350 : : controller);
351 : : }
352 : :
353 : 0 : int sfc_mae_switch_domain_get_intf(uint16_t switch_domain_id,
354 : : int controller,
355 : : efx_pcie_interface_t *intf)
356 : : {
357 : : const efx_pcie_interface_t *controllers;
358 : : size_t nb_controllers;
359 : : int rc;
360 : :
361 : 0 : rc = sfc_mae_switch_domain_controllers(switch_domain_id, &controllers,
362 : : &nb_controllers);
363 [ # # ]: 0 : if (rc != 0)
364 : : return rc;
365 : :
366 [ # # ]: 0 : if (controllers == NULL)
367 : : return ENOENT;
368 : :
369 [ # # ]: 0 : if ((size_t)controller > nb_controllers)
370 : : return EINVAL;
371 : :
372 : 0 : *intf = controllers[controller];
373 : :
374 : 0 : return 0;
375 : : }
376 : :
377 : : /* This function expects to be called only when the lock is held */
378 : : static struct sfc_mae_switch_port *
379 : : sfc_mae_find_switch_port_by_entity(const struct sfc_mae_switch_domain *domain,
380 : : const efx_mport_sel_t *entity_mportp,
381 : : enum sfc_mae_switch_port_type type)
382 : : {
383 : : struct sfc_mae_switch_port *port;
384 : :
385 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
386 : :
387 [ # # # # ]: 0 : TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
388 [ # # # # ]: 0 : if (port->entity_mport.sel == entity_mportp->sel &&
389 [ # # # # ]: 0 : port->type == type)
390 : : return port;
391 : : }
392 : :
393 : : return NULL;
394 : : }
395 : :
396 : : /* This function expects to be called only when the lock is held */
397 : : static int
398 : 0 : sfc_mae_find_switch_port_id_by_entity(uint16_t switch_domain_id,
399 : : const efx_mport_sel_t *entity_mportp,
400 : : enum sfc_mae_switch_port_type type,
401 : : uint16_t *switch_port_id)
402 : : {
403 : : struct sfc_mae_switch_domain *domain;
404 : : struct sfc_mae_switch_port *port;
405 : :
406 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
407 : :
408 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
409 [ # # ]: 0 : if (domain == NULL)
410 : : return EINVAL;
411 : :
412 : : port = sfc_mae_find_switch_port_by_entity(domain, entity_mportp, type);
413 [ # # ]: 0 : if (port == NULL)
414 : : return ENOENT;
415 : :
416 : 0 : *switch_port_id = port->id;
417 : 0 : return 0;
418 : : }
419 : :
420 : : int
421 : 0 : sfc_mae_assign_switch_port(uint16_t switch_domain_id,
422 : : const struct sfc_mae_switch_port_request *req,
423 : : uint16_t *switch_port_id)
424 : : {
425 : : struct sfc_mae_switch_domain *domain;
426 : : struct sfc_mae_switch_port *port;
427 : : int rc;
428 : :
429 : : rte_spinlock_lock(&sfc_mae_switch.lock);
430 : :
431 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
432 [ # # ]: 0 : if (domain == NULL) {
433 : : rc = EINVAL;
434 : 0 : goto fail_find_switch_domain_by_id;
435 : : }
436 : :
437 : 0 : port = sfc_mae_find_switch_port_by_entity(domain, req->entity_mportp,
438 : 0 : req->type);
439 [ # # ]: 0 : if (port != NULL)
440 : 0 : goto done;
441 : :
442 : 0 : port = rte_zmalloc("sfc_mae_switch_port", sizeof(*port), 0);
443 [ # # ]: 0 : if (port == NULL) {
444 : : rc = ENOMEM;
445 : 0 : goto fail_mem_alloc;
446 : : }
447 : :
448 : 0 : port->entity_mport.sel = req->entity_mportp->sel;
449 : 0 : port->type = req->type;
450 : :
451 : 0 : port->id = (domain->nb_ports++);
452 : :
453 : 0 : TAILQ_INSERT_TAIL(&domain->ports, port, switch_domain_ports);
454 : :
455 : 0 : done:
456 : 0 : port->ethdev_mport = *req->ethdev_mportp;
457 : 0 : port->ethdev_port_id = req->ethdev_port_id;
458 : :
459 [ # # ]: 0 : memcpy(&port->data, &req->port_data,
460 : : sizeof(port->data));
461 : :
462 [ # # ]: 0 : switch (req->type) {
463 : 0 : case SFC_MAE_SWITCH_PORT_INDEPENDENT:
464 [ # # ]: 0 : if (port->data.indep.mae_admin) {
465 : : SFC_ASSERT(domain->mae_admin_port == NULL);
466 : 0 : domain->mae_admin_port = port;
467 : : }
468 : : break;
469 : : case SFC_MAE_SWITCH_PORT_REPRESENTOR:
470 : : break;
471 : 0 : default:
472 : : SFC_ASSERT(B_FALSE);
473 : : }
474 : :
475 : 0 : *switch_port_id = port->id;
476 : :
477 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
478 : :
479 : 0 : return 0;
480 : :
481 : : fail_mem_alloc:
482 : 0 : fail_find_switch_domain_by_id:
483 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
484 : 0 : return rc;
485 : : }
486 : :
487 : : int
488 : 0 : sfc_mae_clear_switch_port(uint16_t switch_domain_id,
489 : : uint16_t switch_port_id)
490 : : {
491 : : struct sfc_mae_switch_domain *domain;
492 : : struct sfc_mae_switch_port *port;
493 : :
494 : : rte_spinlock_lock(&sfc_mae_switch.lock);
495 : :
496 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
497 [ # # ]: 0 : if (domain == NULL) {
498 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
499 : 0 : return EINVAL;
500 : : }
501 : :
502 [ # # ]: 0 : if (domain->mae_admin_port != NULL &&
503 [ # # ]: 0 : domain->mae_admin_port->id == switch_port_id) {
504 : 0 : domain->mae_admin_port->data.indep.mae_admin = B_FALSE;
505 : 0 : domain->mae_admin_port = NULL;
506 : : }
507 : :
508 [ # # ]: 0 : TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
509 [ # # ]: 0 : if (port->id == switch_port_id) {
510 : : /*
511 : : * Invalidate the field to prevent wrong
512 : : * look-ups from flow rule handling path.
513 : : */
514 : 0 : port->ethdev_port_id = RTE_MAX_ETHPORTS;
515 : 0 : break;
516 : : }
517 : : }
518 : :
519 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
520 : 0 : return 0;
521 : : }
522 : :
523 : : /* This function expects to be called only when the lock is held */
524 : : static int
525 : : sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id,
526 : : uint16_t ethdev_port_id,
527 : : struct sfc_mae_switch_port **switch_port)
528 : : {
529 : : struct sfc_mae_switch_domain *domain;
530 : : struct sfc_mae_switch_port *port;
531 : :
532 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
533 : :
534 [ # # # # ]: 0 : if (ethdev_port_id == RTE_MAX_ETHPORTS)
535 : : return EINVAL;
536 : :
537 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
538 [ # # # # ]: 0 : if (domain == NULL)
539 : : return EINVAL;
540 : :
541 [ # # # # ]: 0 : TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) {
542 [ # # # # ]: 0 : if (port->ethdev_port_id == ethdev_port_id) {
543 : 0 : *switch_port = port;
544 : : return 0;
545 : : }
546 : : }
547 : :
548 : : return ENOENT;
549 : : }
550 : :
551 : : int
552 : 0 : sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id,
553 : : uint16_t ethdev_port_id,
554 : : unsigned int allowed_mae_switch_port_types,
555 : : efx_mport_sel_t *mport_sel)
556 : : {
557 : : struct sfc_mae_switch_port *port;
558 : : int rc;
559 : :
560 : : rte_spinlock_lock(&sfc_mae_switch.lock);
561 : : rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id,
562 : : ethdev_port_id, &port);
563 : : if (rc != 0)
564 : 0 : goto unlock;
565 : :
566 [ # # ]: 0 : if (((1U << port->type) & allowed_mae_switch_port_types) == 0) {
567 : : rc = ENOTSUP;
568 : 0 : goto unlock;
569 : : }
570 : :
571 : 0 : *mport_sel = port->ethdev_mport;
572 : :
573 : 0 : unlock:
574 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
575 : :
576 : 0 : return rc;
577 : : }
578 : :
579 : : int
580 : 0 : sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id,
581 : : uint16_t ethdev_port_id,
582 : : efx_mport_sel_t *mport_sel)
583 : : {
584 : : static struct sfc_mae_switch_port *port;
585 : : int rc;
586 : :
587 : : rte_spinlock_lock(&sfc_mae_switch.lock);
588 : : rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id,
589 : : ethdev_port_id, &port);
590 : : if (rc != 0)
591 : 0 : goto unlock;
592 : :
593 [ # # ]: 0 : if (port->type == SFC_MAE_SWITCH_PORT_INDEPENDENT &&
594 [ # # ]: 0 : !port->data.indep.mae_admin) {
595 : : /* See sfc_mae_assign_entity_mport() */
596 : : rc = ENOTSUP;
597 : 0 : goto unlock;
598 : : }
599 : :
600 : 0 : *mport_sel = port->entity_mport;
601 : :
602 : 0 : unlock:
603 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
604 : :
605 : 0 : return rc;
606 : : }
607 : :
608 : : int
609 : 0 : sfc_mae_switch_port_id_by_entity(uint16_t switch_domain_id,
610 : : const efx_mport_sel_t *entity_mportp,
611 : : enum sfc_mae_switch_port_type type,
612 : : uint16_t *switch_port_id)
613 : : {
614 : : int rc;
615 : :
616 : : rte_spinlock_lock(&sfc_mae_switch.lock);
617 : 0 : rc = sfc_mae_find_switch_port_id_by_entity(switch_domain_id,
618 : : entity_mportp, type,
619 : : switch_port_id);
620 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
621 : :
622 : 0 : return rc;
623 : : }
624 : :
625 : : static int
626 : : sfc_mae_get_switch_domain_admin_locked(uint16_t switch_domain_id,
627 : : uint16_t *port_id)
628 : : {
629 : : struct sfc_mae_switch_domain *domain;
630 : :
631 : : SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock));
632 : :
633 : : domain = sfc_mae_find_switch_domain_by_id(switch_domain_id);
634 [ # # ]: 0 : if (domain == NULL)
635 : : return EINVAL;
636 : :
637 [ # # ]: 0 : if (domain->mae_admin_port != NULL) {
638 : 0 : *port_id = domain->mae_admin_port->ethdev_port_id;
639 : 0 : return 0;
640 : : }
641 : :
642 : : return ENOENT;
643 : : }
644 : :
645 : : int
646 : 0 : sfc_mae_get_switch_domain_admin(uint16_t switch_domain_id,
647 : : uint16_t *port_id)
648 : : {
649 : : int rc;
650 : :
651 : : rte_spinlock_lock(&sfc_mae_switch.lock);
652 : : rc = sfc_mae_get_switch_domain_admin_locked(switch_domain_id, port_id);
653 : : rte_spinlock_unlock(&sfc_mae_switch.lock);
654 : 0 : return rc;
655 : : }
|