+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;
+}
+