+ unsigned int i;
+
+ sfc_repr_proxy_mbox_handle(rp);
+
+ TAILQ_FOREACH(port, &rp->ports, entries) {
+ if (!port->started)
+ continue;
+
+ for (i = 0; i < rp->nb_txq; i++)
+ sfc_repr_proxy_handle_tx(&rp->dp_txq[i], &port->txq[i]);
+ }
+
+ for (i = 0; i < rp->nb_rxq; i++)
+ sfc_repr_proxy_handle_rx(rp, &rp->dp_rxq[i]);
+
+ return 0;
+}
+
+static struct sfc_txq_info *
+sfc_repr_proxy_txq_info_get(struct sfc_adapter *sa, unsigned int repr_queue_id)
+{
+ struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy_dp_txq *dp_txq;
+
+ SFC_ASSERT(repr_queue_id < sfc_repr_nb_txq(sas));
+ dp_txq = &sa->repr_proxy.dp_txq[repr_queue_id];
+
+ return &sas->txq_info[dp_txq->sw_index];
+}
+
+static int
+sfc_repr_proxy_txq_attach(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
+ sfc_sw_index_t sw_index = sfc_repr_txq_sw_index(sas, i);
+
+ rp->dp_txq[i].sw_index = sw_index;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+}
+
+static void
+sfc_repr_proxy_txq_detach(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_txq(sas); i++)
+ rp->dp_txq[i].sw_index = 0;
+
+ sfc_log_init(sa, "done");
+}
+
+int
+sfc_repr_proxy_txq_init(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ const struct rte_eth_txconf tx_conf = {
+ .tx_free_thresh = SFC_REPR_PROXY_TXQ_FREE_THRESH,
+ };
+ struct sfc_txq_info *txq_info;
+ unsigned int init_i;
+ unsigned int i;
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ if (!sfc_repr_available(sas)) {
+ sfc_log_init(sa, "representors not supported - skip");
+ return 0;
+ }
+
+ for (init_i = 0; init_i < sfc_repr_nb_txq(sas); init_i++) {
+ struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[init_i];
+
+ txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
+ if (txq_info->state == SFC_TXQ_INITIALIZED) {
+ sfc_log_init(sa,
+ "representor proxy TxQ %u is already initialized - skip",
+ init_i);
+ continue;
+ }
+
+ sfc_tx_qinit_info(sa, txq->sw_index);
+
+ rc = sfc_tx_qinit(sa, txq->sw_index,
+ SFC_REPR_PROXY_TX_DESC_COUNT, sa->socket_id,
+ &tx_conf);
+
+ if (rc != 0) {
+ sfc_err(sa, "failed to init representor proxy TxQ %u",
+ init_i);
+ goto fail_init;
+ }
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_init:
+ for (i = 0; i < init_i; i++) {
+ struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
+
+ txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
+ if (txq_info->state == SFC_TXQ_INITIALIZED)
+ sfc_tx_qfini(sa, txq->sw_index);
+ }
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+
+ return rc;
+}
+
+void
+sfc_repr_proxy_txq_fini(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ struct sfc_txq_info *txq_info;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ if (!sfc_repr_available(sas)) {
+ sfc_log_init(sa, "representors not supported - skip");
+ return;
+ }
+
+ for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
+ struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
+
+ txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
+ if (txq_info->state != SFC_TXQ_INITIALIZED) {
+ sfc_log_init(sa,
+ "representor proxy TxQ %u is already finalized - skip",
+ i);
+ continue;
+ }
+
+ sfc_tx_qfini(sa, txq->sw_index);
+ }
+
+ sfc_log_init(sa, "done");
+}
+
+static int
+sfc_repr_proxy_txq_start(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
+ struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
+
+ txq->dp = sfc_repr_proxy_txq_info_get(sa, i)->dp;
+ txq->pkt_burst = sa->eth_dev->tx_pkt_burst;
+ txq->available = 0;
+ txq->transmitted = 0;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+}
+
+static void
+sfc_repr_proxy_txq_stop(struct sfc_adapter *sa)
+{
+ sfc_log_init(sa, "entry");
+ sfc_log_init(sa, "done");
+}
+
+static int
+sfc_repr_proxy_rxq_attach(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
+ sfc_sw_index_t sw_index = sfc_repr_rxq_sw_index(sas, i);
+
+ rp->dp_rxq[i].sw_index = sw_index;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+}
+
+static void
+sfc_repr_proxy_rxq_detach(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
+ rp->dp_rxq[i].sw_index = 0;
+
+ sfc_log_init(sa, "done");
+}
+
+static struct sfc_rxq_info *
+sfc_repr_proxy_rxq_info_get(struct sfc_adapter *sa, unsigned int repr_queue_id)
+{
+ struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy_dp_rxq *dp_rxq;
+
+ SFC_ASSERT(repr_queue_id < sfc_repr_nb_rxq(sas));
+ dp_rxq = &sa->repr_proxy.dp_rxq[repr_queue_id];
+
+ return &sas->rxq_info[dp_rxq->sw_index];
+}
+
+static int
+sfc_repr_proxy_rxq_init(struct sfc_adapter *sa,
+ struct sfc_repr_proxy_dp_rxq *rxq)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ uint16_t nb_rx_desc = SFC_REPR_PROXY_RX_DESC_COUNT;
+ struct sfc_rxq_info *rxq_info;
+ struct rte_eth_rxconf rxconf = {
+ .rx_free_thresh = SFC_REPR_PROXY_RXQ_REFILL_LEVEL,
+ .rx_drop_en = 1,
+ };
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ rxq_info = &sas->rxq_info[rxq->sw_index];
+ if (rxq_info->state & SFC_RXQ_INITIALIZED) {
+ sfc_log_init(sa, "RxQ is already initialized - skip");
+ return 0;
+ }
+
+ nb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);
+ nb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);
+
+ rc = sfc_rx_qinit_info(sa, rxq->sw_index, EFX_RXQ_FLAG_INGRESS_MPORT);
+ if (rc != 0) {
+ sfc_err(sa, "failed to init representor proxy RxQ info");
+ goto fail_repr_rxq_init_info;
+ }
+
+ rc = sfc_rx_qinit(sa, rxq->sw_index, nb_rx_desc, sa->socket_id, &rxconf,
+ rxq->mp);
+ if (rc != 0) {
+ sfc_err(sa, "failed to init representor proxy RxQ");
+ goto fail_repr_rxq_init;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_repr_rxq_init:
+fail_repr_rxq_init_info:
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+
+ return rc;
+}
+
+static void
+sfc_repr_proxy_rxq_fini(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ struct sfc_rxq_info *rxq_info;
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ if (!sfc_repr_available(sas)) {
+ sfc_log_init(sa, "representors not supported - skip");
+ return;
+ }
+
+ for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
+ struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
+
+ rxq_info = &sas->rxq_info[rxq->sw_index];
+ if (rxq_info->state != SFC_RXQ_INITIALIZED) {
+ sfc_log_init(sa,
+ "representor RxQ %u is already finalized - skip",
+ i);
+ continue;
+ }
+
+ sfc_rx_qfini(sa, rxq->sw_index);
+ }
+
+ sfc_log_init(sa, "done");
+}
+
+static void
+sfc_repr_proxy_rxq_stop(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ unsigned int i;
+
+ sfc_log_init(sa, "entry");
+
+ for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
+ sfc_rx_qstop(sa, sa->repr_proxy.dp_rxq[i].sw_index);
+
+ sfc_repr_proxy_rxq_fini(sa);
+
+ sfc_log_init(sa, "done");
+}
+
+static int
+sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ unsigned int i;
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ if (!sfc_repr_available(sas)) {
+ sfc_log_init(sa, "representors not supported - skip");
+ return 0;
+ }
+
+ for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
+ struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
+
+ rc = sfc_repr_proxy_rxq_init(sa, rxq);
+ if (rc != 0) {
+ sfc_err(sa, "failed to init representor proxy RxQ %u",
+ i);
+ goto fail_init;
+ }
+
+ rc = sfc_rx_qstart(sa, rxq->sw_index);
+ if (rc != 0) {
+ sfc_err(sa, "failed to start representor proxy RxQ %u",
+ i);
+ goto fail_start;
+ }
+
+ rxq->dp = sfc_repr_proxy_rxq_info_get(sa, i)->dp;
+ rxq->pkt_burst = sa->eth_dev->rx_pkt_burst;
+ rxq->available = 0;
+ rxq->routed = 0;
+ rxq->forwarded = 0;
+ rxq->stop_route = false;
+ rxq->route_port_id = SFC_REPR_INVALID_ROUTE_PORT_ID;
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_start:
+fail_init:
+ sfc_repr_proxy_rxq_stop(sa);
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+ return rc;
+}
+
+static int
+sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
+ struct sfc_repr_proxy_port *port)
+{
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ efx_mport_sel_t mport_alias_selector;
+ efx_mport_sel_t mport_vf_selector;
+ struct sfc_mae_rule *mae_rule;
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ rc = efx_mae_mport_by_id(&port->egress_mport,
+ &mport_vf_selector);
+ if (rc != 0) {
+ sfc_err(sa, "failed to get VF mport for repr %u",
+ port->repr_id);
+ goto fail_get_vf;
+ }
+
+ rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
+ if (rc != 0) {
+ sfc_err(sa, "failed to get mport selector for repr %u",
+ port->repr_id);
+ goto fail_get_alias;
+ }
+
+ rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
+ &mport_alias_selector, -1,
+ &mae_rule);
+ if (rc != 0) {
+ sfc_err(sa, "failed to insert MAE rule for repr %u",
+ port->repr_id);
+ goto fail_rule_add;
+ }
+
+ port->mae_rule = mae_rule;
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_rule_add:
+fail_get_alias:
+fail_get_vf:
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+ return rc;
+}
+
+static void
+sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
+ struct sfc_repr_proxy_port *port)
+{
+ struct sfc_mae_rule *mae_rule = port->mae_rule;
+
+ sfc_mae_rule_del(sa, mae_rule);
+}
+
+static int
+sfc_repr_proxy_mport_filter_insert(struct sfc_adapter *sa)
+{
+ struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ struct sfc_rxq *rxq_ctrl;
+ struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
+ efx_mport_sel_t mport_alias_selector;
+ static const efx_filter_match_flags_t flags[RTE_DIM(filter->specs)] = {
+ EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
+ EFX_FILTER_MATCH_UNKNOWN_MCAST_DST };
+ unsigned int i;
+ int rc;
+
+ sfc_log_init(sa, "entry");
+
+ if (sfc_repr_nb_rxq(sas) == 1) {
+ rxq_ctrl = &sa->rxq_ctrl[rp->dp_rxq[0].sw_index];
+ } else {
+ sfc_err(sa, "multiple representor proxy RxQs not supported");
+ rc = ENOTSUP;
+ goto fail_multiple_queues;
+ }
+
+ rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
+ if (rc != 0) {
+ sfc_err(sa, "failed to get repr proxy mport by ID");
+ goto fail_get_selector;
+ }
+
+ memset(filter->specs, 0, sizeof(filter->specs));
+ for (i = 0; i < RTE_DIM(filter->specs); i++) {
+ filter->specs[i].efs_priority = EFX_FILTER_PRI_MANUAL;
+ filter->specs[i].efs_flags = EFX_FILTER_FLAG_RX;
+ filter->specs[i].efs_dmaq_id = rxq_ctrl->hw_index;
+ filter->specs[i].efs_match_flags = flags[i] |
+ EFX_FILTER_MATCH_MPORT;
+ filter->specs[i].efs_ingress_mport = mport_alias_selector.sel;
+
+ rc = efx_filter_insert(sa->nic, &filter->specs[i]);
+ if (rc != 0) {
+ sfc_err(sa, "failed to insert repr proxy filter");
+ goto fail_insert;
+ }
+ }
+
+ sfc_log_init(sa, "done");
+
+ return 0;
+
+fail_insert:
+ while (i-- > 0)
+ efx_filter_remove(sa->nic, &filter->specs[i]);
+
+fail_get_selector:
+fail_multiple_queues:
+ sfc_log_init(sa, "failed: %s", rte_strerror(rc));
+ return rc;
+}
+
+static void
+sfc_repr_proxy_mport_filter_remove(struct sfc_adapter *sa)
+{
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
+ unsigned int i;
+
+ for (i = 0; i < RTE_DIM(filter->specs); i++)
+ efx_filter_remove(sa->nic, &filter->specs[i]);
+}
+
+static int
+sfc_repr_proxy_port_rule_insert(struct sfc_adapter *sa,
+ struct sfc_repr_proxy_port *port)
+{
+ int rc;
+
+ rc = sfc_repr_proxy_mae_rule_insert(sa, port);
+ if (rc != 0)
+ goto fail_mae_rule_insert;
+
+ return 0;
+
+fail_mae_rule_insert:
+ return rc;
+}
+
+static void
+sfc_repr_proxy_port_rule_remove(struct sfc_adapter *sa,
+ struct sfc_repr_proxy_port *port)
+{
+ sfc_repr_proxy_mae_rule_remove(sa, port);
+}
+
+static int
+sfc_repr_proxy_ports_init(struct sfc_adapter *sa)
+{
+ struct sfc_repr_proxy *rp = &sa->repr_proxy;
+ int rc;