11e7fbdf0SIvan Malov /* SPDX-License-Identifier: BSD-3-Clause 21e7fbdf0SIvan Malov * 398d26ef7SAndrew Rybchenko * Copyright(c) 2019-2021 Xilinx, Inc. 41e7fbdf0SIvan Malov * Copyright(c) 2019 Solarflare Communications Inc. 51e7fbdf0SIvan Malov * 61e7fbdf0SIvan Malov * This software was jointly developed between OKTET Labs (under contract 71e7fbdf0SIvan Malov * for Solarflare) and Solarflare Communications, Inc. 81e7fbdf0SIvan Malov */ 91e7fbdf0SIvan Malov 101e7fbdf0SIvan Malov #include <stdbool.h> 111e7fbdf0SIvan Malov 121e7fbdf0SIvan Malov #include <rte_common.h> 131e7fbdf0SIvan Malov #include <rte_spinlock.h> 141e7fbdf0SIvan Malov 151e7fbdf0SIvan Malov #include "efx.h" 161e7fbdf0SIvan Malov 171e7fbdf0SIvan Malov #include "sfc.h" 181e7fbdf0SIvan Malov #include "sfc_log.h" 191e7fbdf0SIvan Malov #include "sfc_switch.h" 201e7fbdf0SIvan Malov 211e7fbdf0SIvan Malov /** 221e7fbdf0SIvan Malov * Switch port registry entry. 231e7fbdf0SIvan Malov * 241e7fbdf0SIvan Malov * Drivers aware of RTE switch domains also have to maintain RTE switch 251e7fbdf0SIvan Malov * port IDs for RTE ethdev instances they operate. These IDs are supposed 261e7fbdf0SIvan Malov * to stand for physical interconnect entities, in example, PCIe functions. 271e7fbdf0SIvan Malov * 281e7fbdf0SIvan Malov * In terms of MAE, a physical interconnect entity can be referred to using 291e7fbdf0SIvan Malov * an MPORT selector, that is, a 32-bit value. RTE switch port IDs, in turn, 301e7fbdf0SIvan Malov * are 16-bit values, so indirect mapping has to be maintained: 311e7fbdf0SIvan Malov * 321e7fbdf0SIvan Malov * +--------------------+ +---------------------------------------+ 331e7fbdf0SIvan Malov * | RTE switch port ID | ------ | MAE switch port entry | 341e7fbdf0SIvan Malov * +--------------------+ | --------------------- | 351e7fbdf0SIvan Malov * | | 361e7fbdf0SIvan Malov * | Entity (PCIe function) MPORT selector | 371e7fbdf0SIvan Malov * | + | 381e7fbdf0SIvan Malov * | Port type (independent/representor) | 391e7fbdf0SIvan Malov * +---------------------------------------+ 401e7fbdf0SIvan Malov * 411e7fbdf0SIvan Malov * This mapping comprises a port type to ensure that RTE switch port ID 421e7fbdf0SIvan Malov * of a represented entity and that of its representor are different in 431e7fbdf0SIvan Malov * the case when the entity gets plugged into DPDK and not into a guest. 441fb65e4dSIvan Malov * 451fb65e4dSIvan Malov * Entry data also comprises RTE ethdev's own MPORT. This value 461fb65e4dSIvan Malov * coincides with the entity MPORT in the case of independent ports. 471fb65e4dSIvan Malov * In the case of representors, this ID is not a selector and refers 481fb65e4dSIvan Malov * to an allocatable object (that is, it's likely to change on RTE 491fb65e4dSIvan Malov * ethdev replug). Flow API backend must use this value rather 501fb65e4dSIvan Malov * than entity_mport to support flow rule action PORT_ID. 511e7fbdf0SIvan Malov */ 521e7fbdf0SIvan Malov struct sfc_mae_switch_port { 531e7fbdf0SIvan Malov TAILQ_ENTRY(sfc_mae_switch_port) switch_domain_ports; 541e7fbdf0SIvan Malov 551fb65e4dSIvan Malov /** RTE ethdev MPORT */ 561fb65e4dSIvan Malov efx_mport_sel_t ethdev_mport; 571fb65e4dSIvan Malov /** RTE ethdev port ID */ 581fb65e4dSIvan Malov uint16_t ethdev_port_id; 591fb65e4dSIvan Malov 601e7fbdf0SIvan Malov /** Entity (PCIe function) MPORT selector */ 611e7fbdf0SIvan Malov efx_mport_sel_t entity_mport; 621e7fbdf0SIvan Malov /** Port type (independent/representor) */ 631e7fbdf0SIvan Malov enum sfc_mae_switch_port_type type; 641e7fbdf0SIvan Malov /** RTE switch port ID */ 651e7fbdf0SIvan Malov uint16_t id; 66768d1e44SViacheslav Galaktionov 67768d1e44SViacheslav Galaktionov union sfc_mae_switch_port_data data; 681e7fbdf0SIvan Malov }; 691e7fbdf0SIvan Malov 701e7fbdf0SIvan Malov TAILQ_HEAD(sfc_mae_switch_ports, sfc_mae_switch_port); 711e7fbdf0SIvan Malov 721e7fbdf0SIvan Malov /** 731e7fbdf0SIvan Malov * Switch domain registry entry. 741e7fbdf0SIvan Malov * 751e7fbdf0SIvan Malov * Even if an RTE ethdev instance gets unplugged, the corresponding 761e7fbdf0SIvan Malov * entry in the switch port registry will not be removed because the 771e7fbdf0SIvan Malov * entity (PCIe function) MPORT is static and cannot change. If this 781e7fbdf0SIvan Malov * RTE ethdev gets plugged back, the entry will be reused, and 791e7fbdf0SIvan Malov * RTE switch port ID will be the same. 801e7fbdf0SIvan Malov */ 811e7fbdf0SIvan Malov struct sfc_mae_switch_domain { 821e7fbdf0SIvan Malov TAILQ_ENTRY(sfc_mae_switch_domain) entries; 831e7fbdf0SIvan Malov 841e7fbdf0SIvan Malov /** HW switch ID */ 851e7fbdf0SIvan Malov struct sfc_hw_switch_id *hw_switch_id; 861e7fbdf0SIvan Malov /** The number of ports in the switch port registry */ 871e7fbdf0SIvan Malov unsigned int nb_ports; 881e7fbdf0SIvan Malov /** Switch port registry */ 891e7fbdf0SIvan Malov struct sfc_mae_switch_ports ports; 901e7fbdf0SIvan Malov /** RTE switch domain ID allocated for a group of devices */ 911e7fbdf0SIvan Malov uint16_t id; 9244db08d5SViacheslav Galaktionov /** DPDK controller -> EFX interface mapping */ 9344db08d5SViacheslav Galaktionov efx_pcie_interface_t *controllers; 9444db08d5SViacheslav Galaktionov /** Number of DPDK controllers and EFX interfaces */ 9544db08d5SViacheslav Galaktionov size_t nb_controllers; 961e7fbdf0SIvan Malov }; 971e7fbdf0SIvan Malov 981e7fbdf0SIvan Malov TAILQ_HEAD(sfc_mae_switch_domains, sfc_mae_switch_domain); 991e7fbdf0SIvan Malov 1001e7fbdf0SIvan Malov /** 1011e7fbdf0SIvan Malov * MAE representation of RTE switch infrastructure. 1021e7fbdf0SIvan Malov * 1031e7fbdf0SIvan Malov * It is possible that an RTE flow API client tries to insert a rule 1041e7fbdf0SIvan Malov * referencing an RTE ethdev deployed on top of a different physical 1051e7fbdf0SIvan Malov * device (it may belong to the same vendor or not). This particular 1061e7fbdf0SIvan Malov * driver/engine cannot support this and has to turn down such rules. 1071e7fbdf0SIvan Malov * 1081e7fbdf0SIvan Malov * Technically, it's HW switch identifier which, if queried for each 1091e7fbdf0SIvan Malov * RTE ethdev instance, indicates relationship between the instances. 1101e7fbdf0SIvan Malov * In the meantime, RTE flow API clients also need to somehow figure 1111e7fbdf0SIvan Malov * out relationship between RTE ethdev instances in advance. 1121e7fbdf0SIvan Malov * 1131e7fbdf0SIvan Malov * The concept of RTE switch domains resolves this issue. The driver 1141e7fbdf0SIvan Malov * maintains a static list of switch domains which is easy to browse, 1151e7fbdf0SIvan Malov * and each RTE ethdev fills RTE switch parameters in device 1161e7fbdf0SIvan Malov * information structure which is made available to clients. 1171e7fbdf0SIvan Malov * 1181e7fbdf0SIvan Malov * Even if all RTE ethdev instances belonging to a switch domain get 1191e7fbdf0SIvan Malov * unplugged, the corresponding entry in the switch domain registry 1201e7fbdf0SIvan Malov * will not be removed because the corresponding HW switch exists 1211e7fbdf0SIvan Malov * regardless of its ports being plugged to DPDK or kept aside. 1221e7fbdf0SIvan Malov * If a port gets plugged back to DPDK, the corresponding 1231e7fbdf0SIvan Malov * RTE ethdev will indicate the same RTE switch domain ID. 1241e7fbdf0SIvan Malov */ 1251e7fbdf0SIvan Malov struct sfc_mae_switch { 1261e7fbdf0SIvan Malov /** A lock to protect the whole structure */ 1271e7fbdf0SIvan Malov rte_spinlock_t lock; 1281e7fbdf0SIvan Malov /** Switch domain registry */ 1291e7fbdf0SIvan Malov struct sfc_mae_switch_domains domains; 1301e7fbdf0SIvan Malov }; 1311e7fbdf0SIvan Malov 1321e7fbdf0SIvan Malov static struct sfc_mae_switch sfc_mae_switch = { 1331e7fbdf0SIvan Malov .lock = RTE_SPINLOCK_INITIALIZER, 1341e7fbdf0SIvan Malov .domains = TAILQ_HEAD_INITIALIZER(sfc_mae_switch.domains), 1351e7fbdf0SIvan Malov }; 1361e7fbdf0SIvan Malov 1371e7fbdf0SIvan Malov 1381e7fbdf0SIvan Malov /* This function expects to be called only when the lock is held */ 1391e7fbdf0SIvan Malov static struct sfc_mae_switch_domain * 1401e7fbdf0SIvan Malov sfc_mae_find_switch_domain_by_id(uint16_t switch_domain_id) 1411e7fbdf0SIvan Malov { 1421e7fbdf0SIvan Malov struct sfc_mae_switch_domain *domain; 1431e7fbdf0SIvan Malov 1441e7fbdf0SIvan Malov SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); 1451e7fbdf0SIvan Malov 1461e7fbdf0SIvan Malov TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) { 1471e7fbdf0SIvan Malov if (domain->id == switch_domain_id) 1481e7fbdf0SIvan Malov return domain; 1491e7fbdf0SIvan Malov } 1501e7fbdf0SIvan Malov 1511e7fbdf0SIvan Malov return NULL; 1521e7fbdf0SIvan Malov } 1531e7fbdf0SIvan Malov 1541e7fbdf0SIvan Malov /* This function expects to be called only when the lock is held */ 1551e7fbdf0SIvan Malov static struct sfc_mae_switch_domain * 1561e7fbdf0SIvan Malov sfc_mae_find_switch_domain_by_hw_switch_id(const struct sfc_hw_switch_id *id) 1571e7fbdf0SIvan Malov { 1581e7fbdf0SIvan Malov struct sfc_mae_switch_domain *domain; 1591e7fbdf0SIvan Malov 1601e7fbdf0SIvan Malov SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); 1611e7fbdf0SIvan Malov 1621e7fbdf0SIvan Malov TAILQ_FOREACH(domain, &sfc_mae_switch.domains, entries) { 1631e7fbdf0SIvan Malov if (sfc_hw_switch_ids_equal(domain->hw_switch_id, id)) 1641e7fbdf0SIvan Malov return domain; 1651e7fbdf0SIvan Malov } 1661e7fbdf0SIvan Malov 1671e7fbdf0SIvan Malov return NULL; 1681e7fbdf0SIvan Malov } 1691e7fbdf0SIvan Malov 1701e7fbdf0SIvan Malov int 1711e7fbdf0SIvan Malov sfc_mae_assign_switch_domain(struct sfc_adapter *sa, 1721e7fbdf0SIvan Malov uint16_t *switch_domain_id) 1731e7fbdf0SIvan Malov { 1741e7fbdf0SIvan Malov struct sfc_hw_switch_id *hw_switch_id; 1751e7fbdf0SIvan Malov struct sfc_mae_switch_domain *domain; 1761e7fbdf0SIvan Malov int rc; 1771e7fbdf0SIvan Malov 1781e7fbdf0SIvan Malov rte_spinlock_lock(&sfc_mae_switch.lock); 1791e7fbdf0SIvan Malov 1801e7fbdf0SIvan Malov rc = sfc_hw_switch_id_init(sa, &hw_switch_id); 1811e7fbdf0SIvan Malov if (rc != 0) 1821e7fbdf0SIvan Malov goto fail_hw_switch_id_init; 1831e7fbdf0SIvan Malov 1841e7fbdf0SIvan Malov domain = sfc_mae_find_switch_domain_by_hw_switch_id(hw_switch_id); 1851e7fbdf0SIvan Malov if (domain != NULL) { 1861e7fbdf0SIvan Malov sfc_hw_switch_id_fini(sa, hw_switch_id); 1871e7fbdf0SIvan Malov goto done; 1881e7fbdf0SIvan Malov } 1891e7fbdf0SIvan Malov 1901e7fbdf0SIvan Malov domain = rte_zmalloc("sfc_mae_switch_domain", sizeof(*domain), 0); 1911e7fbdf0SIvan Malov if (domain == NULL) { 1921e7fbdf0SIvan Malov rc = ENOMEM; 1931e7fbdf0SIvan Malov goto fail_mem_alloc; 1941e7fbdf0SIvan Malov } 1951e7fbdf0SIvan Malov 1961e7fbdf0SIvan Malov /* 1971e7fbdf0SIvan Malov * This code belongs to driver init path, that is, negation is 1981e7fbdf0SIvan Malov * done at the end of the path by sfc_eth_dev_init(). RTE APIs 1991e7fbdf0SIvan Malov * negate error codes, so drop negation here. 2001e7fbdf0SIvan Malov */ 2011e7fbdf0SIvan Malov rc = -rte_eth_switch_domain_alloc(&domain->id); 2021e7fbdf0SIvan Malov if (rc != 0) 2031e7fbdf0SIvan Malov goto fail_domain_alloc; 2041e7fbdf0SIvan Malov 2051e7fbdf0SIvan Malov domain->hw_switch_id = hw_switch_id; 2061e7fbdf0SIvan Malov 2071e7fbdf0SIvan Malov TAILQ_INIT(&domain->ports); 2081e7fbdf0SIvan Malov 2091e7fbdf0SIvan Malov TAILQ_INSERT_TAIL(&sfc_mae_switch.domains, domain, entries); 2101e7fbdf0SIvan Malov 2111e7fbdf0SIvan Malov done: 2121e7fbdf0SIvan Malov *switch_domain_id = domain->id; 2131e7fbdf0SIvan Malov 2141e7fbdf0SIvan Malov rte_spinlock_unlock(&sfc_mae_switch.lock); 2151e7fbdf0SIvan Malov 2161e7fbdf0SIvan Malov return 0; 2171e7fbdf0SIvan Malov 2181e7fbdf0SIvan Malov fail_domain_alloc: 2191e7fbdf0SIvan Malov rte_free(domain); 2201e7fbdf0SIvan Malov 2211e7fbdf0SIvan Malov fail_mem_alloc: 2221e7fbdf0SIvan Malov sfc_hw_switch_id_fini(sa, hw_switch_id); 2231e7fbdf0SIvan Malov 2241e7fbdf0SIvan Malov fail_hw_switch_id_init: 225c7e64eeaSViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 2261e7fbdf0SIvan Malov return rc; 2271e7fbdf0SIvan Malov } 2281e7fbdf0SIvan Malov 22944db08d5SViacheslav Galaktionov int 23044db08d5SViacheslav Galaktionov sfc_mae_switch_domain_controllers(uint16_t switch_domain_id, 23144db08d5SViacheslav Galaktionov const efx_pcie_interface_t **controllers, 23244db08d5SViacheslav Galaktionov size_t *nb_controllers) 23344db08d5SViacheslav Galaktionov { 23444db08d5SViacheslav Galaktionov struct sfc_mae_switch_domain *domain; 23544db08d5SViacheslav Galaktionov 23644db08d5SViacheslav Galaktionov if (controllers == NULL || nb_controllers == NULL) 23744db08d5SViacheslav Galaktionov return EINVAL; 23844db08d5SViacheslav Galaktionov 23944db08d5SViacheslav Galaktionov rte_spinlock_lock(&sfc_mae_switch.lock); 24044db08d5SViacheslav Galaktionov 24144db08d5SViacheslav Galaktionov domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); 24244db08d5SViacheslav Galaktionov if (domain == NULL) { 24344db08d5SViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 24444db08d5SViacheslav Galaktionov return EINVAL; 24544db08d5SViacheslav Galaktionov } 24644db08d5SViacheslav Galaktionov 24744db08d5SViacheslav Galaktionov *controllers = domain->controllers; 24844db08d5SViacheslav Galaktionov *nb_controllers = domain->nb_controllers; 24944db08d5SViacheslav Galaktionov 25044db08d5SViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 25144db08d5SViacheslav Galaktionov return 0; 25244db08d5SViacheslav Galaktionov } 25344db08d5SViacheslav Galaktionov 25444db08d5SViacheslav Galaktionov int 25544db08d5SViacheslav Galaktionov sfc_mae_switch_domain_map_controllers(uint16_t switch_domain_id, 25644db08d5SViacheslav Galaktionov efx_pcie_interface_t *controllers, 25744db08d5SViacheslav Galaktionov size_t nb_controllers) 25844db08d5SViacheslav Galaktionov { 25944db08d5SViacheslav Galaktionov struct sfc_mae_switch_domain *domain; 26044db08d5SViacheslav Galaktionov 26144db08d5SViacheslav Galaktionov rte_spinlock_lock(&sfc_mae_switch.lock); 26244db08d5SViacheslav Galaktionov 26344db08d5SViacheslav Galaktionov domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); 26444db08d5SViacheslav Galaktionov if (domain == NULL) { 26544db08d5SViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 26644db08d5SViacheslav Galaktionov return EINVAL; 26744db08d5SViacheslav Galaktionov } 26844db08d5SViacheslav Galaktionov 26944db08d5SViacheslav Galaktionov /* Controller mapping may be set only once */ 27044db08d5SViacheslav Galaktionov if (domain->controllers != NULL) { 27144db08d5SViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 27244db08d5SViacheslav Galaktionov return EINVAL; 27344db08d5SViacheslav Galaktionov } 27444db08d5SViacheslav Galaktionov 27544db08d5SViacheslav Galaktionov domain->controllers = controllers; 27644db08d5SViacheslav Galaktionov domain->nb_controllers = nb_controllers; 27744db08d5SViacheslav Galaktionov 27844db08d5SViacheslav Galaktionov rte_spinlock_unlock(&sfc_mae_switch.lock); 27944db08d5SViacheslav Galaktionov return 0; 28044db08d5SViacheslav Galaktionov } 28144db08d5SViacheslav Galaktionov 282*c75d560dSViacheslav Galaktionov int 283*c75d560dSViacheslav Galaktionov sfc_mae_switch_domain_get_controller(uint16_t switch_domain_id, 284*c75d560dSViacheslav Galaktionov efx_pcie_interface_t intf, 285*c75d560dSViacheslav Galaktionov int *controller) 286*c75d560dSViacheslav Galaktionov { 287*c75d560dSViacheslav Galaktionov const efx_pcie_interface_t *controllers; 288*c75d560dSViacheslav Galaktionov size_t nb_controllers; 289*c75d560dSViacheslav Galaktionov size_t i; 290*c75d560dSViacheslav Galaktionov int rc; 291*c75d560dSViacheslav Galaktionov 292*c75d560dSViacheslav Galaktionov rc = sfc_mae_switch_domain_controllers(switch_domain_id, &controllers, 293*c75d560dSViacheslav Galaktionov &nb_controllers); 294*c75d560dSViacheslav Galaktionov if (rc != 0) 295*c75d560dSViacheslav Galaktionov return rc; 296*c75d560dSViacheslav Galaktionov 297*c75d560dSViacheslav Galaktionov if (controllers == NULL) 298*c75d560dSViacheslav Galaktionov return ENOENT; 299*c75d560dSViacheslav Galaktionov 300*c75d560dSViacheslav Galaktionov for (i = 0; i < nb_controllers; i++) { 301*c75d560dSViacheslav Galaktionov if (controllers[i] == intf) { 302*c75d560dSViacheslav Galaktionov *controller = i; 303*c75d560dSViacheslav Galaktionov return 0; 304*c75d560dSViacheslav Galaktionov } 305*c75d560dSViacheslav Galaktionov } 306*c75d560dSViacheslav Galaktionov 307*c75d560dSViacheslav Galaktionov return ENOENT; 308*c75d560dSViacheslav Galaktionov } 309*c75d560dSViacheslav Galaktionov 3101e7fbdf0SIvan Malov /* This function expects to be called only when the lock is held */ 3111e7fbdf0SIvan Malov static struct sfc_mae_switch_port * 3121e7fbdf0SIvan Malov sfc_mae_find_switch_port_by_entity(const struct sfc_mae_switch_domain *domain, 3131e7fbdf0SIvan Malov const efx_mport_sel_t *entity_mportp, 3141e7fbdf0SIvan Malov enum sfc_mae_switch_port_type type) 3151e7fbdf0SIvan Malov { 3161e7fbdf0SIvan Malov struct sfc_mae_switch_port *port; 3171e7fbdf0SIvan Malov 3181e7fbdf0SIvan Malov SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); 3191e7fbdf0SIvan Malov 3201e7fbdf0SIvan Malov TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) { 3211e7fbdf0SIvan Malov if (port->entity_mport.sel == entity_mportp->sel && 3221e7fbdf0SIvan Malov port->type == type) 3231e7fbdf0SIvan Malov return port; 3241e7fbdf0SIvan Malov } 3251e7fbdf0SIvan Malov 3261e7fbdf0SIvan Malov return NULL; 3271e7fbdf0SIvan Malov } 3281e7fbdf0SIvan Malov 3291e7fbdf0SIvan Malov int 3301e7fbdf0SIvan Malov sfc_mae_assign_switch_port(uint16_t switch_domain_id, 3311e7fbdf0SIvan Malov const struct sfc_mae_switch_port_request *req, 3321e7fbdf0SIvan Malov uint16_t *switch_port_id) 3331e7fbdf0SIvan Malov { 3341e7fbdf0SIvan Malov struct sfc_mae_switch_domain *domain; 3351e7fbdf0SIvan Malov struct sfc_mae_switch_port *port; 3361e7fbdf0SIvan Malov int rc; 3371e7fbdf0SIvan Malov 3381e7fbdf0SIvan Malov rte_spinlock_lock(&sfc_mae_switch.lock); 3391e7fbdf0SIvan Malov 3401e7fbdf0SIvan Malov domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); 3411e7fbdf0SIvan Malov if (domain == NULL) { 3421e7fbdf0SIvan Malov rc = EINVAL; 3431e7fbdf0SIvan Malov goto fail_find_switch_domain_by_id; 3441e7fbdf0SIvan Malov } 3451e7fbdf0SIvan Malov 3461e7fbdf0SIvan Malov port = sfc_mae_find_switch_port_by_entity(domain, req->entity_mportp, 3471e7fbdf0SIvan Malov req->type); 3481e7fbdf0SIvan Malov if (port != NULL) 3491e7fbdf0SIvan Malov goto done; 3501e7fbdf0SIvan Malov 3511e7fbdf0SIvan Malov port = rte_zmalloc("sfc_mae_switch_port", sizeof(*port), 0); 3521e7fbdf0SIvan Malov if (port == NULL) { 3531e7fbdf0SIvan Malov rc = ENOMEM; 3541e7fbdf0SIvan Malov goto fail_mem_alloc; 3551e7fbdf0SIvan Malov } 3561e7fbdf0SIvan Malov 3571e7fbdf0SIvan Malov port->entity_mport.sel = req->entity_mportp->sel; 3581e7fbdf0SIvan Malov port->type = req->type; 3591e7fbdf0SIvan Malov 3601e7fbdf0SIvan Malov port->id = (domain->nb_ports++); 3611e7fbdf0SIvan Malov 3621e7fbdf0SIvan Malov TAILQ_INSERT_TAIL(&domain->ports, port, switch_domain_ports); 3631e7fbdf0SIvan Malov 3641e7fbdf0SIvan Malov done: 3651fb65e4dSIvan Malov port->ethdev_mport = *req->ethdev_mportp; 3661fb65e4dSIvan Malov port->ethdev_port_id = req->ethdev_port_id; 3671fb65e4dSIvan Malov 368768d1e44SViacheslav Galaktionov switch (req->type) { 369768d1e44SViacheslav Galaktionov case SFC_MAE_SWITCH_PORT_INDEPENDENT: 370768d1e44SViacheslav Galaktionov /* No data */ 371768d1e44SViacheslav Galaktionov break; 372768d1e44SViacheslav Galaktionov case SFC_MAE_SWITCH_PORT_REPRESENTOR: 373768d1e44SViacheslav Galaktionov memcpy(&port->data.repr, &req->port_data, 374768d1e44SViacheslav Galaktionov sizeof(port->data.repr)); 375768d1e44SViacheslav Galaktionov break; 376768d1e44SViacheslav Galaktionov default: 377768d1e44SViacheslav Galaktionov SFC_ASSERT(B_FALSE); 378768d1e44SViacheslav Galaktionov } 379768d1e44SViacheslav Galaktionov 3801e7fbdf0SIvan Malov *switch_port_id = port->id; 3811e7fbdf0SIvan Malov 3821e7fbdf0SIvan Malov rte_spinlock_unlock(&sfc_mae_switch.lock); 3831e7fbdf0SIvan Malov 3841e7fbdf0SIvan Malov return 0; 3851e7fbdf0SIvan Malov 3861e7fbdf0SIvan Malov fail_mem_alloc: 3871e7fbdf0SIvan Malov fail_find_switch_domain_by_id: 3881e7fbdf0SIvan Malov rte_spinlock_unlock(&sfc_mae_switch.lock); 3891e7fbdf0SIvan Malov return rc; 3901e7fbdf0SIvan Malov } 3911fb65e4dSIvan Malov 3921fb65e4dSIvan Malov /* This function expects to be called only when the lock is held */ 3931fb65e4dSIvan Malov static int 3941fb65e4dSIvan Malov sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id, 3951fb65e4dSIvan Malov uint16_t ethdev_port_id, 3961fb65e4dSIvan Malov efx_mport_sel_t *mport_sel) 3971fb65e4dSIvan Malov { 3981fb65e4dSIvan Malov struct sfc_mae_switch_domain *domain; 3991fb65e4dSIvan Malov struct sfc_mae_switch_port *port; 4001fb65e4dSIvan Malov 4011fb65e4dSIvan Malov SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); 4021fb65e4dSIvan Malov 4031fb65e4dSIvan Malov if (ethdev_port_id == RTE_MAX_ETHPORTS) 4041fb65e4dSIvan Malov return EINVAL; 4051fb65e4dSIvan Malov 4061fb65e4dSIvan Malov domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); 4071fb65e4dSIvan Malov if (domain == NULL) 4081fb65e4dSIvan Malov return EINVAL; 4091fb65e4dSIvan Malov 4101fb65e4dSIvan Malov TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) { 4111fb65e4dSIvan Malov if (port->ethdev_port_id == ethdev_port_id) { 4121fb65e4dSIvan Malov *mport_sel = port->ethdev_mport; 4131fb65e4dSIvan Malov return 0; 4141fb65e4dSIvan Malov } 4151fb65e4dSIvan Malov } 4161fb65e4dSIvan Malov 4171fb65e4dSIvan Malov return ENOENT; 4181fb65e4dSIvan Malov } 4191fb65e4dSIvan Malov 4201fb65e4dSIvan Malov int 4211fb65e4dSIvan Malov sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id, 4221fb65e4dSIvan Malov uint16_t ethdev_port_id, 4231fb65e4dSIvan Malov efx_mport_sel_t *mport_sel) 4241fb65e4dSIvan Malov { 4251fb65e4dSIvan Malov int rc; 4261fb65e4dSIvan Malov 4271fb65e4dSIvan Malov rte_spinlock_lock(&sfc_mae_switch.lock); 4281fb65e4dSIvan Malov rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id, 4291fb65e4dSIvan Malov ethdev_port_id, mport_sel); 4301fb65e4dSIvan Malov rte_spinlock_unlock(&sfc_mae_switch.lock); 4311fb65e4dSIvan Malov 4321fb65e4dSIvan Malov return rc; 4331fb65e4dSIvan Malov } 434