X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_repr.c;h=4dbb6bdaa3d673769bfc569d89ddc68babd5b94d;hb=472fa1b17c270ce44a2640dad0da27f4867b5088;hp=d9c7c7ae9d5cb73f4bb44e6536b487c6f523379b;hpb=155583abe63cee8ffb5fc4a276c03641f492d750;p=dpdk.git diff --git a/drivers/net/sfc/sfc_repr.c b/drivers/net/sfc/sfc_repr.c index d9c7c7ae9d..4dbb6bdaa3 100644 --- a/drivers/net/sfc/sfc_repr.c +++ b/drivers/net/sfc/sfc_repr.c @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -21,6 +22,7 @@ #include "sfc_ethdev_state.h" #include "sfc_repr_proxy_api.h" #include "sfc_switch.h" +#include "sfc_dp_tx.h" /** Multi-process shared representor private data */ struct sfc_repr_shared { @@ -136,6 +138,179 @@ sfc_repr_lock_fini(__rte_unused struct sfc_repr *sr) /* Just for symmetry of the API */ } +static void +sfc_repr_rx_queue_stop(void *queue) +{ + struct sfc_repr_rxq *rxq = queue; + + if (rxq == NULL) + return; + + rte_ring_reset(rxq->ring); +} + +static void +sfc_repr_tx_queue_stop(void *queue) +{ + struct sfc_repr_txq *txq = queue; + + if (txq == NULL) + return; + + rte_ring_reset(txq->ring); +} + +static int +sfc_repr_start(struct rte_eth_dev *dev) +{ + struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + struct sfc_repr_shared *srs; + int ret; + + sfcr_info(sr, "entry"); + + SFC_ASSERT(sfc_repr_lock_is_locked(sr)); + + switch (sr->state) { + case SFC_ETHDEV_CONFIGURED: + break; + case SFC_ETHDEV_STARTED: + sfcr_info(sr, "already started"); + return 0; + default: + ret = -EINVAL; + goto fail_bad_state; + } + + sr->state = SFC_ETHDEV_STARTING; + + srs = sfc_repr_shared_by_eth_dev(dev); + ret = sfc_repr_proxy_start_repr(srs->pf_port_id, srs->repr_id); + if (ret != 0) { + SFC_ASSERT(ret > 0); + ret = -ret; + goto fail_start; + } + + sr->state = SFC_ETHDEV_STARTED; + + sfcr_info(sr, "done"); + + return 0; + +fail_start: + sr->state = SFC_ETHDEV_CONFIGURED; + +fail_bad_state: + sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret)); + return ret; +} + +static int +sfc_repr_dev_start(struct rte_eth_dev *dev) +{ + struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + int ret; + + sfcr_info(sr, "entry"); + + sfc_repr_lock(sr); + ret = sfc_repr_start(dev); + sfc_repr_unlock(sr); + + if (ret != 0) + goto fail_start; + + sfcr_info(sr, "done"); + + return 0; + +fail_start: + sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret)); + return ret; +} + +static int +sfc_repr_stop(struct rte_eth_dev *dev) +{ + struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + struct sfc_repr_shared *srs; + unsigned int i; + int ret; + + sfcr_info(sr, "entry"); + + SFC_ASSERT(sfc_repr_lock_is_locked(sr)); + + switch (sr->state) { + case SFC_ETHDEV_STARTED: + break; + case SFC_ETHDEV_CONFIGURED: + sfcr_info(sr, "already stopped"); + return 0; + default: + sfcr_err(sr, "stop in unexpected state %u", sr->state); + SFC_ASSERT(B_FALSE); + ret = -EINVAL; + goto fail_bad_state; + } + + srs = sfc_repr_shared_by_eth_dev(dev); + ret = sfc_repr_proxy_stop_repr(srs->pf_port_id, srs->repr_id); + if (ret != 0) { + SFC_ASSERT(ret > 0); + ret = -ret; + goto fail_stop; + } + + for (i = 0; i < dev->data->nb_rx_queues; i++) + sfc_repr_rx_queue_stop(dev->data->rx_queues[i]); + + for (i = 0; i < dev->data->nb_tx_queues; i++) + sfc_repr_tx_queue_stop(dev->data->tx_queues[i]); + + sr->state = SFC_ETHDEV_CONFIGURED; + sfcr_info(sr, "done"); + + return 0; + +fail_bad_state: +fail_stop: + sfcr_err(sr, "%s() failed: %s", __func__, rte_strerror(-ret)); + + return ret; +} + +static int +sfc_repr_dev_stop(struct rte_eth_dev *dev) +{ + struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + int ret; + + sfcr_info(sr, "entry"); + + sfc_repr_lock(sr); + + ret = sfc_repr_stop(dev); + if (ret != 0) { + sfcr_err(sr, "%s() failed to stop representor", __func__); + goto fail_stop; + } + + sfc_repr_unlock(sr); + + sfcr_info(sr, "done"); + + return 0; + +fail_stop: + sfc_repr_unlock(sr); + + sfcr_err(sr, "%s() failed %s", __func__, rte_strerror(-ret)); + + return ret; +} + static int sfc_repr_check_conf(struct sfc_repr *sr, uint16_t nb_rx_queues, const struct rte_eth_conf *conf) @@ -288,6 +463,24 @@ sfc_repr_dev_infos_get(struct rte_eth_dev *dev, return 0; } +static int +sfc_repr_dev_link_update(struct rte_eth_dev *dev, + __rte_unused int wait_to_complete) +{ + struct sfc_repr *sr = sfc_repr_by_eth_dev(dev); + struct rte_eth_link link; + + if (sr->state != SFC_ETHDEV_STARTED) { + sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, &link); + } else { + memset(&link, 0, sizeof(link)); + link.link_status = ETH_LINK_UP; + link.link_speed = ETH_SPEED_NUM_UNKNOWN; + } + + return rte_eth_linkstatus_set(dev, &link); +} + static int sfc_repr_ring_create(uint16_t pf_port_id, uint16_t repr_id, const char *type_name, uint16_t qid, uint16_t nb_desc, @@ -535,6 +728,10 @@ sfc_repr_dev_close(struct rte_eth_dev *dev) sfc_repr_lock(sr); switch (sr->state) { + case SFC_ETHDEV_STARTED: + sfc_repr_stop(dev); + SFC_ASSERT(sr->state == SFC_ETHDEV_CONFIGURED); + /* FALLTHROUGH */ case SFC_ETHDEV_CONFIGURED: sfc_repr_close(sr); SFC_ASSERT(sr->state == SFC_ETHDEV_INITIALIZED); @@ -577,8 +774,11 @@ sfc_repr_dev_close(struct rte_eth_dev *dev) static const struct eth_dev_ops sfc_repr_dev_ops = { .dev_configure = sfc_repr_dev_configure, + .dev_start = sfc_repr_dev_start, + .dev_stop = sfc_repr_dev_stop, .dev_close = sfc_repr_dev_close, .dev_infos_get = sfc_repr_dev_infos_get, + .link_update = sfc_repr_dev_link_update, .rx_queue_setup = sfc_repr_rx_queue_setup, .rx_queue_release = sfc_repr_rx_queue_release, .tx_queue_setup = sfc_repr_tx_queue_setup, @@ -708,6 +908,7 @@ sfc_repr_create(struct rte_eth_dev *parent, uint16_t representor_id, struct sfc_repr_init_data repr_data; char name[RTE_ETH_NAME_MAX_LEN]; int ret; + struct rte_eth_dev *dev; if (snprintf(name, sizeof(name), "net_%s_representor_%u", parent->device->name, representor_id) >= @@ -716,20 +917,24 @@ sfc_repr_create(struct rte_eth_dev *parent, uint16_t representor_id, return -ENAMETOOLONG; } - memset(&repr_data, 0, sizeof(repr_data)); - repr_data.pf_port_id = parent->data->port_id; - repr_data.repr_id = representor_id; - repr_data.switch_domain_id = switch_domain_id; - repr_data.mport_sel = *mport_sel; - - ret = rte_eth_dev_create(parent->device, name, - sizeof(struct sfc_repr_shared), - NULL, NULL, - sfc_repr_eth_dev_init, &repr_data); - if (ret != 0) - SFC_GENERIC_LOG(ERR, "%s() failed to create device", __func__); - - SFC_GENERIC_LOG(INFO, "%s() done: %s", __func__, rte_strerror(-ret)); + dev = rte_eth_dev_allocated(name); + if (dev == NULL) { + memset(&repr_data, 0, sizeof(repr_data)); + repr_data.pf_port_id = parent->data->port_id; + repr_data.repr_id = representor_id; + repr_data.switch_domain_id = switch_domain_id; + repr_data.mport_sel = *mport_sel; + + ret = rte_eth_dev_create(parent->device, name, + sizeof(struct sfc_repr_shared), + NULL, NULL, + sfc_repr_eth_dev_init, &repr_data); + if (ret != 0) { + SFC_GENERIC_LOG(ERR, "%s() failed to create device", + __func__); + return ret; + } + } - return ret; + return 0; }