X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_switch.c;h=5c10e8fc7423feeff5f4cab1597b2cfec4abafe9;hb=369ce46248c0605d31bd29ebaa4474309a875176;hp=225d07fa15193610f9cb1260281213cde7453d1f;hpb=c75d560db32b04b29472dc9d91e63ab39e8945b8;p=dpdk.git diff --git a/drivers/net/sfc/sfc_switch.c b/drivers/net/sfc/sfc_switch.c index 225d07fa15..5c10e8fc74 100644 --- a/drivers/net/sfc/sfc_switch.c +++ b/drivers/net/sfc/sfc_switch.c @@ -93,6 +93,8 @@ struct sfc_mae_switch_domain { efx_pcie_interface_t *controllers; /** Number of DPDK controllers and EFX interfaces */ size_t nb_controllers; + /** MAE admin port */ + struct sfc_mae_switch_port *mae_admin_port; }; TAILQ_HEAD(sfc_mae_switch_domains, sfc_mae_switch_domain); @@ -151,6 +153,34 @@ sfc_mae_find_switch_domain_by_id(uint16_t switch_domain_id) return NULL; } +int +sfc_mae_switch_ports_iterate(uint16_t switch_domain_id, + sfc_mae_switch_port_iterator_cb *cb, + void *data) +{ + struct sfc_mae_switch_domain *domain; + struct sfc_mae_switch_port *port; + + if (cb == NULL) + return EINVAL; + + rte_spinlock_lock(&sfc_mae_switch.lock); + + domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); + if (domain == NULL) { + rte_spinlock_unlock(&sfc_mae_switch.lock); + return EINVAL; + } + + TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) { + cb(port->type, &port->ethdev_mport, port->ethdev_port_id, + &port->entity_mport, port->id, &port->data, data); + } + + rte_spinlock_unlock(&sfc_mae_switch.lock); + return 0; +} + /* This function expects to be called only when the lock is held */ static struct sfc_mae_switch_domain * sfc_mae_find_switch_domain_by_hw_switch_id(const struct sfc_hw_switch_id *id) @@ -279,6 +309,27 @@ sfc_mae_switch_domain_map_controllers(uint16_t switch_domain_id, return 0; } +int +sfc_mae_switch_controller_from_mapping(const efx_pcie_interface_t *controllers, + size_t nb_controllers, + efx_pcie_interface_t intf, + int *controller) +{ + size_t i; + + if (controllers == NULL) + return ENOENT; + + for (i = 0; i < nb_controllers; i++) { + if (controllers[i] == intf) { + *controller = i; + return 0; + } + } + + return ENOENT; +} + int sfc_mae_switch_domain_get_controller(uint16_t switch_domain_id, efx_pcie_interface_t intf, @@ -286,7 +337,25 @@ sfc_mae_switch_domain_get_controller(uint16_t switch_domain_id, { const efx_pcie_interface_t *controllers; size_t nb_controllers; - size_t i; + int rc; + + rc = sfc_mae_switch_domain_controllers(switch_domain_id, &controllers, + &nb_controllers); + if (rc != 0) + return rc; + + return sfc_mae_switch_controller_from_mapping(controllers, + nb_controllers, + intf, + controller); +} + +int sfc_mae_switch_domain_get_intf(uint16_t switch_domain_id, + int controller, + efx_pcie_interface_t *intf) +{ + const efx_pcie_interface_t *controllers; + size_t nb_controllers; int rc; rc = sfc_mae_switch_domain_controllers(switch_domain_id, &controllers, @@ -297,14 +366,12 @@ sfc_mae_switch_domain_get_controller(uint16_t switch_domain_id, if (controllers == NULL) return ENOENT; - for (i = 0; i < nb_controllers; i++) { - if (controllers[i] == intf) { - *controller = i; - return 0; - } - } + if ((size_t)controller > nb_controllers) + return EINVAL; - return ENOENT; + *intf = controllers[controller]; + + return 0; } /* This function expects to be called only when the lock is held */ @@ -326,6 +393,30 @@ sfc_mae_find_switch_port_by_entity(const struct sfc_mae_switch_domain *domain, return NULL; } +/* This function expects to be called only when the lock is held */ +static int +sfc_mae_find_switch_port_id_by_entity(uint16_t switch_domain_id, + const efx_mport_sel_t *entity_mportp, + enum sfc_mae_switch_port_type type, + uint16_t *switch_port_id) +{ + struct sfc_mae_switch_domain *domain; + struct sfc_mae_switch_port *port; + + SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); + + domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); + if (domain == NULL) + return EINVAL; + + port = sfc_mae_find_switch_port_by_entity(domain, entity_mportp, type); + if (port == NULL) + return ENOENT; + + *switch_port_id = port->id; + return 0; +} + int sfc_mae_assign_switch_port(uint16_t switch_domain_id, const struct sfc_mae_switch_port_request *req, @@ -365,13 +456,17 @@ done: port->ethdev_mport = *req->ethdev_mportp; port->ethdev_port_id = req->ethdev_port_id; + memcpy(&port->data, &req->port_data, + sizeof(port->data)); + switch (req->type) { case SFC_MAE_SWITCH_PORT_INDEPENDENT: - /* No data */ + if (port->data.indep.mae_admin) { + SFC_ASSERT(domain->mae_admin_port == NULL); + domain->mae_admin_port = port; + } break; case SFC_MAE_SWITCH_PORT_REPRESENTOR: - memcpy(&port->data.repr, &req->port_data, - sizeof(port->data.repr)); break; default: SFC_ASSERT(B_FALSE); @@ -389,11 +484,35 @@ fail_find_switch_domain_by_id: return rc; } +int +sfc_mae_clear_switch_port(uint16_t switch_domain_id, + uint16_t switch_port_id) +{ + struct sfc_mae_switch_domain *domain; + + rte_spinlock_lock(&sfc_mae_switch.lock); + + domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); + if (domain == NULL) { + rte_spinlock_unlock(&sfc_mae_switch.lock); + return EINVAL; + } + + if (domain->mae_admin_port != NULL && + domain->mae_admin_port->id == switch_port_id) { + domain->mae_admin_port->data.indep.mae_admin = B_FALSE; + domain->mae_admin_port = NULL; + } + + rte_spinlock_unlock(&sfc_mae_switch.lock); + return 0; +} + /* This function expects to be called only when the lock is held */ static int sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id, uint16_t ethdev_port_id, - efx_mport_sel_t *mport_sel) + struct sfc_mae_switch_port **switch_port) { struct sfc_mae_switch_domain *domain; struct sfc_mae_switch_port *port; @@ -409,7 +528,7 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id, TAILQ_FOREACH(port, &domain->ports, switch_domain_ports) { if (port->ethdev_port_id == ethdev_port_id) { - *mport_sel = port->ethdev_mport; + *switch_port = port; return 0; } } @@ -418,16 +537,110 @@ sfc_mae_find_switch_port_by_ethdev(uint16_t switch_domain_id, } int -sfc_mae_switch_port_by_ethdev(uint16_t switch_domain_id, - uint16_t ethdev_port_id, - efx_mport_sel_t *mport_sel) +sfc_mae_switch_get_ethdev_mport(uint16_t switch_domain_id, + uint16_t ethdev_port_id, + efx_mport_sel_t *mport_sel) { + struct sfc_mae_switch_port *port; int rc; rte_spinlock_lock(&sfc_mae_switch.lock); rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id, - ethdev_port_id, mport_sel); + ethdev_port_id, &port); + if (rc != 0) + goto unlock; + + if (port->type != SFC_MAE_SWITCH_PORT_INDEPENDENT) { + /* + * The ethdev is a "VF representor". It does not own + * a dedicated m-port suitable for use in flow rules. + */ + rc = ENOTSUP; + goto unlock; + } + + *mport_sel = port->ethdev_mport; + +unlock: rte_spinlock_unlock(&sfc_mae_switch.lock); return rc; } + +int +sfc_mae_switch_get_entity_mport(uint16_t switch_domain_id, + uint16_t ethdev_port_id, + efx_mport_sel_t *mport_sel) +{ + static struct sfc_mae_switch_port *port; + int rc; + + rte_spinlock_lock(&sfc_mae_switch.lock); + rc = sfc_mae_find_switch_port_by_ethdev(switch_domain_id, + ethdev_port_id, &port); + if (rc != 0) + goto unlock; + + if (port->type == SFC_MAE_SWITCH_PORT_INDEPENDENT && + !port->data.indep.mae_admin) { + /* See sfc_mae_assign_entity_mport() */ + rc = ENOTSUP; + goto unlock; + } + + *mport_sel = port->entity_mport; + +unlock: + rte_spinlock_unlock(&sfc_mae_switch.lock); + + return rc; +} + +int +sfc_mae_switch_port_id_by_entity(uint16_t switch_domain_id, + const efx_mport_sel_t *entity_mportp, + enum sfc_mae_switch_port_type type, + uint16_t *switch_port_id) +{ + int rc; + + rte_spinlock_lock(&sfc_mae_switch.lock); + rc = sfc_mae_find_switch_port_id_by_entity(switch_domain_id, + entity_mportp, type, + switch_port_id); + rte_spinlock_unlock(&sfc_mae_switch.lock); + + return rc; +} + +static int +sfc_mae_get_switch_domain_admin_locked(uint16_t switch_domain_id, + uint16_t *port_id) +{ + struct sfc_mae_switch_domain *domain; + + SFC_ASSERT(rte_spinlock_is_locked(&sfc_mae_switch.lock)); + + domain = sfc_mae_find_switch_domain_by_id(switch_domain_id); + if (domain == NULL) + return EINVAL; + + if (domain->mae_admin_port != NULL) { + *port_id = domain->mae_admin_port->ethdev_port_id; + return 0; + } + + return ENOENT; +} + +int +sfc_mae_get_switch_domain_admin(uint16_t switch_domain_id, + uint16_t *port_id) +{ + int rc; + + rte_spinlock_lock(&sfc_mae_switch.lock); + rc = sfc_mae_get_switch_domain_admin_locked(switch_domain_id, port_id); + rte_spinlock_unlock(&sfc_mae_switch.lock); + return rc; +}