dpdk/drivers/net/sfc/sfc_repr_proxy.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 *
   3 * Copyright(c) 2019-2021 Xilinx, Inc.
   4 * Copyright(c) 2019 Solarflare Communications Inc.
   5 *
   6 * This software was jointly developed between OKTET Labs (under contract
   7 * for Solarflare) and Solarflare Communications, Inc.
   8 */
   9
  10#include <rte_service.h>
  11#include <rte_service_component.h>
  12
  13#include "sfc_log.h"
  14#include "sfc_service.h"
  15#include "sfc_repr_proxy.h"
  16#include "sfc_repr_proxy_api.h"
  17#include "sfc.h"
  18#include "sfc_ev.h"
  19#include "sfc_rx.h"
  20#include "sfc_tx.h"
  21#include "sfc_dp_rx.h"
  22
  23/**
  24 * Amount of time to wait for the representor proxy routine (which is
  25 * running on a service core) to handle a request sent via mbox.
  26 */
  27#define SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS     1000
  28
  29/**
  30 * Amount of time to wait for the representor proxy routine (which is
  31 * running on a service core) to terminate after service core is stopped.
  32 */
  33#define SFC_REPR_PROXY_ROUTINE_TERMINATE_TIMEOUT_MS     10000
  34
  35#define SFC_REPR_INVALID_ROUTE_PORT_ID  (UINT16_MAX)
  36
  37static struct sfc_repr_proxy *
  38sfc_repr_proxy_by_adapter(struct sfc_adapter *sa)
  39{
  40        return &sa->repr_proxy;
  41}
  42
  43static struct sfc_adapter *
  44sfc_get_adapter_by_pf_port_id(uint16_t pf_port_id)
  45{
  46        struct rte_eth_dev *dev;
  47        struct sfc_adapter *sa;
  48
  49        SFC_ASSERT(pf_port_id < RTE_MAX_ETHPORTS);
  50
  51        dev = &rte_eth_devices[pf_port_id];
  52        sa = sfc_adapter_by_eth_dev(dev);
  53
  54        sfc_adapter_lock(sa);
  55
  56        return sa;
  57}
  58
  59static void
  60sfc_put_adapter(struct sfc_adapter *sa)
  61{
  62        sfc_adapter_unlock(sa);
  63}
  64
  65static struct sfc_repr_proxy_port *
  66sfc_repr_proxy_find_port(struct sfc_repr_proxy *rp, uint16_t repr_id)
  67{
  68        struct sfc_repr_proxy_port *port;
  69
  70        TAILQ_FOREACH(port, &rp->ports, entries) {
  71                if (port->repr_id == repr_id)
  72                        return port;
  73        }
  74
  75        return NULL;
  76}
  77
  78static int
  79sfc_repr_proxy_mbox_send(struct sfc_repr_proxy_mbox *mbox,
  80                         struct sfc_repr_proxy_port *port,
  81                         enum sfc_repr_proxy_mbox_op op)
  82{
  83        const unsigned int wait_ms = SFC_REPR_PROXY_MBOX_POLL_TIMEOUT_MS;
  84        unsigned int i;
  85
  86        mbox->op = op;
  87        mbox->port = port;
  88        mbox->ack = false;
  89
  90        /*
  91         * Release ordering enforces marker set after data is populated.
  92         * Paired with acquire ordering in sfc_repr_proxy_mbox_handle().
  93         */
  94        __atomic_store_n(&mbox->write_marker, true, __ATOMIC_RELEASE);
  95
  96        /*
  97         * Wait for the representor routine to process the request.
  98         * Give up on timeout.
  99         */
 100        for (i = 0; i < wait_ms; i++) {
 101                /*
 102                 * Paired with release ordering in sfc_repr_proxy_mbox_handle()
 103                 * on acknowledge write.
 104                 */
 105                if (__atomic_load_n(&mbox->ack, __ATOMIC_ACQUIRE))
 106                        break;
 107
 108                rte_delay_ms(1);
 109        }
 110
 111        if (i == wait_ms) {
 112                SFC_GENERIC_LOG(ERR,
 113                        "%s() failed to wait for representor proxy routine ack",
 114                        __func__);
 115                return ETIMEDOUT;
 116        }
 117
 118        return 0;
 119}
 120
 121static void
 122sfc_repr_proxy_mbox_handle(struct sfc_repr_proxy *rp)
 123{
 124        struct sfc_repr_proxy_mbox *mbox = &rp->mbox;
 125
 126        /*
 127         * Paired with release ordering in sfc_repr_proxy_mbox_send()
 128         * on marker set.
 129         */
 130        if (!__atomic_load_n(&mbox->write_marker, __ATOMIC_ACQUIRE))
 131                return;
 132
 133        mbox->write_marker = false;
 134
 135        switch (mbox->op) {
 136        case SFC_REPR_PROXY_MBOX_ADD_PORT:
 137                TAILQ_INSERT_TAIL(&rp->ports, mbox->port, entries);
 138                break;
 139        case SFC_REPR_PROXY_MBOX_DEL_PORT:
 140                TAILQ_REMOVE(&rp->ports, mbox->port, entries);
 141                break;
 142        case SFC_REPR_PROXY_MBOX_START_PORT:
 143                mbox->port->started = true;
 144                break;
 145        case SFC_REPR_PROXY_MBOX_STOP_PORT:
 146                mbox->port->started = false;
 147                break;
 148        default:
 149                SFC_ASSERT(0);
 150                return;
 151        }
 152
 153        /*
 154         * Paired with acquire ordering in sfc_repr_proxy_mbox_send()
 155         * on acknowledge read.
 156         */
 157        __atomic_store_n(&mbox->ack, true, __ATOMIC_RELEASE);
 158}
 159
 160static void
 161sfc_repr_proxy_handle_tx(struct sfc_repr_proxy_dp_txq *rp_txq,
 162                         struct sfc_repr_proxy_txq *repr_txq)
 163{
 164        /*
 165         * With multiple representor proxy queues configured it is
 166         * possible that not all of the corresponding representor
 167         * queues were created. Skip the queues that do not exist.
 168         */
 169        if (repr_txq->ring == NULL)
 170                return;
 171
 172        if (rp_txq->available < RTE_DIM(rp_txq->tx_pkts)) {
 173                rp_txq->available +=
 174                        rte_ring_sc_dequeue_burst(repr_txq->ring,
 175                                (void **)(&rp_txq->tx_pkts[rp_txq->available]),
 176                                RTE_DIM(rp_txq->tx_pkts) - rp_txq->available,
 177                                NULL);
 178
 179                if (rp_txq->available == rp_txq->transmitted)
 180                        return;
 181        }
 182
 183        rp_txq->transmitted += rp_txq->pkt_burst(rp_txq->dp,
 184                                &rp_txq->tx_pkts[rp_txq->transmitted],
 185                                rp_txq->available - rp_txq->transmitted);
 186
 187        if (rp_txq->available == rp_txq->transmitted) {
 188                rp_txq->available = 0;
 189                rp_txq->transmitted = 0;
 190        }
 191}
 192
 193static struct sfc_repr_proxy_port *
 194sfc_repr_proxy_rx_route_mbuf(struct sfc_repr_proxy *rp, struct rte_mbuf *m)
 195{
 196        struct sfc_repr_proxy_port *port;
 197        efx_mport_id_t mport_id;
 198
 199        mport_id.id = *RTE_MBUF_DYNFIELD(m, sfc_dp_mport_offset,
 200                                         typeof(&((efx_mport_id_t *)0)->id));
 201
 202        TAILQ_FOREACH(port, &rp->ports, entries) {
 203                if (port->egress_mport.id == mport_id.id) {
 204                        m->port = port->rte_port_id;
 205                        m->ol_flags &= ~sfc_dp_mport_override;
 206                        return port;
 207                }
 208        }
 209
 210        return NULL;
 211}
 212
 213/*
 214 * Returns true if a packet is encountered which should be forwarded to a
 215 * port which is different from the one that is currently routed.
 216 */
 217static bool
 218sfc_repr_proxy_rx_route(struct sfc_repr_proxy *rp,
 219                        struct sfc_repr_proxy_dp_rxq *rp_rxq)
 220{
 221        unsigned int i;
 222
 223        for (i = rp_rxq->routed;
 224             i < rp_rxq->available && !rp_rxq->stop_route;
 225             i++, rp_rxq->routed++) {
 226                struct sfc_repr_proxy_port *port;
 227                struct rte_mbuf *m = rp_rxq->pkts[i];
 228
 229                port = sfc_repr_proxy_rx_route_mbuf(rp, m);
 230                /* Cannot find destination representor */
 231                if (port == NULL) {
 232                        /* Effectively drop the packet */
 233                        rp_rxq->forwarded++;
 234                        continue;
 235                }
 236
 237                /* Currently routed packets are mapped to a different port */
 238                if (port->repr_id != rp_rxq->route_port_id &&
 239                    rp_rxq->route_port_id != SFC_REPR_INVALID_ROUTE_PORT_ID)
 240                        return true;
 241
 242                rp_rxq->route_port_id = port->repr_id;
 243        }
 244
 245        return false;
 246}
 247
 248static void
 249sfc_repr_proxy_rx_forward(struct sfc_repr_proxy *rp,
 250                          struct sfc_repr_proxy_dp_rxq *rp_rxq)
 251{
 252        struct sfc_repr_proxy_port *port;
 253
 254        if (rp_rxq->route_port_id != SFC_REPR_INVALID_ROUTE_PORT_ID) {
 255                port = sfc_repr_proxy_find_port(rp, rp_rxq->route_port_id);
 256
 257                if (port != NULL && port->started) {
 258                        rp_rxq->forwarded +=
 259                            rte_ring_sp_enqueue_burst(port->rxq[0].ring,
 260                                (void **)(&rp_rxq->pkts[rp_rxq->forwarded]),
 261                                rp_rxq->routed - rp_rxq->forwarded, NULL);
 262                } else {
 263                        /* Drop all routed packets if the port is not started */
 264                        rp_rxq->forwarded = rp_rxq->routed;
 265                }
 266        }
 267
 268        if (rp_rxq->forwarded == rp_rxq->routed) {
 269                rp_rxq->route_port_id = SFC_REPR_INVALID_ROUTE_PORT_ID;
 270                rp_rxq->stop_route = false;
 271        } else {
 272                /* Stall packet routing if not all packets were forwarded */
 273                rp_rxq->stop_route = true;
 274        }
 275
 276        if (rp_rxq->available == rp_rxq->forwarded)
 277                rp_rxq->available = rp_rxq->forwarded = rp_rxq->routed = 0;
 278}
 279
 280static void
 281sfc_repr_proxy_handle_rx(struct sfc_repr_proxy *rp,
 282                         struct sfc_repr_proxy_dp_rxq *rp_rxq)
 283{
 284        bool route_again;
 285
 286        if (rp_rxq->available < RTE_DIM(rp_rxq->pkts)) {
 287                rp_rxq->available += rp_rxq->pkt_burst(rp_rxq->dp,
 288                                &rp_rxq->pkts[rp_rxq->available],
 289                                RTE_DIM(rp_rxq->pkts) - rp_rxq->available);
 290                if (rp_rxq->available == rp_rxq->forwarded)
 291                        return;
 292        }
 293
 294        do {
 295                route_again = sfc_repr_proxy_rx_route(rp, rp_rxq);
 296                sfc_repr_proxy_rx_forward(rp, rp_rxq);
 297        } while (route_again && !rp_rxq->stop_route);
 298}
 299
 300static int32_t
 301sfc_repr_proxy_routine(void *arg)
 302{
 303        struct sfc_repr_proxy_port *port;
 304        struct sfc_repr_proxy *rp = arg;
 305        unsigned int i;
 306
 307        sfc_repr_proxy_mbox_handle(rp);
 308
 309        TAILQ_FOREACH(port, &rp->ports, entries) {
 310                if (!port->started)
 311                        continue;
 312
 313                for (i = 0; i < rp->nb_txq; i++)
 314                        sfc_repr_proxy_handle_tx(&rp->dp_txq[i], &port->txq[i]);
 315        }
 316
 317        for (i = 0; i < rp->nb_rxq; i++)
 318                sfc_repr_proxy_handle_rx(rp, &rp->dp_rxq[i]);
 319
 320        return 0;
 321}
 322
 323static struct sfc_txq_info *
 324sfc_repr_proxy_txq_info_get(struct sfc_adapter *sa, unsigned int repr_queue_id)
 325{
 326        struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 327        struct sfc_repr_proxy_dp_txq *dp_txq;
 328
 329        SFC_ASSERT(repr_queue_id < sfc_repr_nb_txq(sas));
 330        dp_txq = &sa->repr_proxy.dp_txq[repr_queue_id];
 331
 332        return &sas->txq_info[dp_txq->sw_index];
 333}
 334
 335static int
 336sfc_repr_proxy_txq_attach(struct sfc_adapter *sa)
 337{
 338        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 339        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 340        unsigned int i;
 341
 342        sfc_log_init(sa, "entry");
 343
 344        for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
 345                sfc_sw_index_t sw_index = sfc_repr_txq_sw_index(sas, i);
 346
 347                rp->dp_txq[i].sw_index = sw_index;
 348        }
 349
 350        sfc_log_init(sa, "done");
 351
 352        return 0;
 353}
 354
 355static void
 356sfc_repr_proxy_txq_detach(struct sfc_adapter *sa)
 357{
 358        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 359        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 360        unsigned int i;
 361
 362        sfc_log_init(sa, "entry");
 363
 364        for (i = 0; i < sfc_repr_nb_txq(sas); i++)
 365                rp->dp_txq[i].sw_index = 0;
 366
 367        sfc_log_init(sa, "done");
 368}
 369
 370int
 371sfc_repr_proxy_txq_init(struct sfc_adapter *sa)
 372{
 373        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 374        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 375        const struct rte_eth_txconf tx_conf = {
 376                .tx_free_thresh = SFC_REPR_PROXY_TXQ_FREE_THRESH,
 377        };
 378        struct sfc_txq_info *txq_info;
 379        unsigned int init_i;
 380        unsigned int i;
 381        int rc;
 382
 383        sfc_log_init(sa, "entry");
 384
 385        if (!sfc_repr_available(sas)) {
 386                sfc_log_init(sa, "representors not supported - skip");
 387                return 0;
 388        }
 389
 390        for (init_i = 0; init_i < sfc_repr_nb_txq(sas); init_i++) {
 391                struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[init_i];
 392
 393                txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
 394                if (txq_info->state == SFC_TXQ_INITIALIZED) {
 395                        sfc_log_init(sa,
 396                                "representor proxy TxQ %u is already initialized - skip",
 397                                init_i);
 398                        continue;
 399                }
 400
 401                sfc_tx_qinit_info(sa, txq->sw_index);
 402
 403                rc = sfc_tx_qinit(sa, txq->sw_index,
 404                                  SFC_REPR_PROXY_TX_DESC_COUNT, sa->socket_id,
 405                                  &tx_conf);
 406
 407                if (rc != 0) {
 408                        sfc_err(sa, "failed to init representor proxy TxQ %u",
 409                                init_i);
 410                        goto fail_init;
 411                }
 412        }
 413
 414        sfc_log_init(sa, "done");
 415
 416        return 0;
 417
 418fail_init:
 419        for (i = 0; i < init_i; i++) {
 420                struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
 421
 422                txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
 423                if (txq_info->state == SFC_TXQ_INITIALIZED)
 424                        sfc_tx_qfini(sa, txq->sw_index);
 425        }
 426        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 427
 428        return rc;
 429}
 430
 431void
 432sfc_repr_proxy_txq_fini(struct sfc_adapter *sa)
 433{
 434        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 435        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 436        struct sfc_txq_info *txq_info;
 437        unsigned int i;
 438
 439        sfc_log_init(sa, "entry");
 440
 441        if (!sfc_repr_available(sas)) {
 442                sfc_log_init(sa, "representors not supported - skip");
 443                return;
 444        }
 445
 446        for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
 447                struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
 448
 449                txq_info = &sfc_sa2shared(sa)->txq_info[txq->sw_index];
 450                if (txq_info->state != SFC_TXQ_INITIALIZED) {
 451                        sfc_log_init(sa,
 452                                "representor proxy TxQ %u is already finalized - skip",
 453                                i);
 454                        continue;
 455                }
 456
 457                sfc_tx_qfini(sa, txq->sw_index);
 458        }
 459
 460        sfc_log_init(sa, "done");
 461}
 462
 463static int
 464sfc_repr_proxy_txq_start(struct sfc_adapter *sa)
 465{
 466        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 467        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 468        unsigned int i;
 469
 470        sfc_log_init(sa, "entry");
 471
 472        for (i = 0; i < sfc_repr_nb_txq(sas); i++) {
 473                struct sfc_repr_proxy_dp_txq *txq = &rp->dp_txq[i];
 474
 475                txq->dp = sfc_repr_proxy_txq_info_get(sa, i)->dp;
 476                txq->pkt_burst = sa->eth_dev->tx_pkt_burst;
 477                txq->available = 0;
 478                txq->transmitted = 0;
 479        }
 480
 481        sfc_log_init(sa, "done");
 482
 483        return 0;
 484}
 485
 486static void
 487sfc_repr_proxy_txq_stop(struct sfc_adapter *sa)
 488{
 489        sfc_log_init(sa, "entry");
 490        sfc_log_init(sa, "done");
 491}
 492
 493static int
 494sfc_repr_proxy_rxq_attach(struct sfc_adapter *sa)
 495{
 496        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 497        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 498        unsigned int i;
 499
 500        sfc_log_init(sa, "entry");
 501
 502        for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
 503                sfc_sw_index_t sw_index = sfc_repr_rxq_sw_index(sas, i);
 504
 505                rp->dp_rxq[i].sw_index = sw_index;
 506        }
 507
 508        sfc_log_init(sa, "done");
 509
 510        return 0;
 511}
 512
 513static void
 514sfc_repr_proxy_rxq_detach(struct sfc_adapter *sa)
 515{
 516        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 517        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 518        unsigned int i;
 519
 520        sfc_log_init(sa, "entry");
 521
 522        for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
 523                rp->dp_rxq[i].sw_index = 0;
 524
 525        sfc_log_init(sa, "done");
 526}
 527
 528static struct sfc_rxq_info *
 529sfc_repr_proxy_rxq_info_get(struct sfc_adapter *sa, unsigned int repr_queue_id)
 530{
 531        struct sfc_adapter_shared *sas = sfc_sa2shared(sa);
 532        struct sfc_repr_proxy_dp_rxq *dp_rxq;
 533
 534        SFC_ASSERT(repr_queue_id < sfc_repr_nb_rxq(sas));
 535        dp_rxq = &sa->repr_proxy.dp_rxq[repr_queue_id];
 536
 537        return &sas->rxq_info[dp_rxq->sw_index];
 538}
 539
 540static int
 541sfc_repr_proxy_rxq_init(struct sfc_adapter *sa,
 542                        struct sfc_repr_proxy_dp_rxq *rxq)
 543{
 544        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 545        uint16_t nb_rx_desc = SFC_REPR_PROXY_RX_DESC_COUNT;
 546        struct sfc_rxq_info *rxq_info;
 547        struct rte_eth_rxconf rxconf = {
 548                .rx_free_thresh = SFC_REPR_PROXY_RXQ_REFILL_LEVEL,
 549                .rx_drop_en = 1,
 550        };
 551        int rc;
 552
 553        sfc_log_init(sa, "entry");
 554
 555        rxq_info = &sas->rxq_info[rxq->sw_index];
 556        if (rxq_info->state & SFC_RXQ_INITIALIZED) {
 557                sfc_log_init(sa, "RxQ is already initialized - skip");
 558                return 0;
 559        }
 560
 561        nb_rx_desc = RTE_MIN(nb_rx_desc, sa->rxq_max_entries);
 562        nb_rx_desc = RTE_MAX(nb_rx_desc, sa->rxq_min_entries);
 563
 564        rc = sfc_rx_qinit_info(sa, rxq->sw_index, EFX_RXQ_FLAG_INGRESS_MPORT);
 565        if (rc != 0) {
 566                sfc_err(sa, "failed to init representor proxy RxQ info");
 567                goto fail_repr_rxq_init_info;
 568        }
 569
 570        rc = sfc_rx_qinit(sa, rxq->sw_index, nb_rx_desc, sa->socket_id, &rxconf,
 571                          rxq->mp);
 572        if (rc != 0) {
 573                sfc_err(sa, "failed to init representor proxy RxQ");
 574                goto fail_repr_rxq_init;
 575        }
 576
 577        sfc_log_init(sa, "done");
 578
 579        return 0;
 580
 581fail_repr_rxq_init:
 582fail_repr_rxq_init_info:
 583        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 584
 585        return rc;
 586}
 587
 588static void
 589sfc_repr_proxy_rxq_fini(struct sfc_adapter *sa)
 590{
 591        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 592        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 593        struct sfc_rxq_info *rxq_info;
 594        unsigned int i;
 595
 596        sfc_log_init(sa, "entry");
 597
 598        if (!sfc_repr_available(sas)) {
 599                sfc_log_init(sa, "representors not supported - skip");
 600                return;
 601        }
 602
 603        for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
 604                struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
 605
 606                rxq_info = &sas->rxq_info[rxq->sw_index];
 607                if (rxq_info->state != SFC_RXQ_INITIALIZED) {
 608                        sfc_log_init(sa,
 609                                "representor RxQ %u is already finalized - skip",
 610                                i);
 611                        continue;
 612                }
 613
 614                sfc_rx_qfini(sa, rxq->sw_index);
 615        }
 616
 617        sfc_log_init(sa, "done");
 618}
 619
 620static void
 621sfc_repr_proxy_rxq_stop(struct sfc_adapter *sa)
 622{
 623        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 624        unsigned int i;
 625
 626        sfc_log_init(sa, "entry");
 627
 628        for (i = 0; i < sfc_repr_nb_rxq(sas); i++)
 629                sfc_rx_qstop(sa, sa->repr_proxy.dp_rxq[i].sw_index);
 630
 631        sfc_repr_proxy_rxq_fini(sa);
 632
 633        sfc_log_init(sa, "done");
 634}
 635
 636static int
 637sfc_repr_proxy_rxq_start(struct sfc_adapter *sa)
 638{
 639        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 640        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 641        unsigned int i;
 642        int rc;
 643
 644        sfc_log_init(sa, "entry");
 645
 646        if (!sfc_repr_available(sas)) {
 647                sfc_log_init(sa, "representors not supported - skip");
 648                return 0;
 649        }
 650
 651        for (i = 0; i < sfc_repr_nb_rxq(sas); i++) {
 652                struct sfc_repr_proxy_dp_rxq *rxq = &rp->dp_rxq[i];
 653
 654                rc = sfc_repr_proxy_rxq_init(sa, rxq);
 655                if (rc != 0) {
 656                        sfc_err(sa, "failed to init representor proxy RxQ %u",
 657                                i);
 658                        goto fail_init;
 659                }
 660
 661                rc = sfc_rx_qstart(sa, rxq->sw_index);
 662                if (rc != 0) {
 663                        sfc_err(sa, "failed to start representor proxy RxQ %u",
 664                                i);
 665                        goto fail_start;
 666                }
 667
 668                rxq->dp = sfc_repr_proxy_rxq_info_get(sa, i)->dp;
 669                rxq->pkt_burst = sa->eth_dev->rx_pkt_burst;
 670                rxq->available = 0;
 671                rxq->routed = 0;
 672                rxq->forwarded = 0;
 673                rxq->stop_route = false;
 674                rxq->route_port_id = SFC_REPR_INVALID_ROUTE_PORT_ID;
 675        }
 676
 677        sfc_log_init(sa, "done");
 678
 679        return 0;
 680
 681fail_start:
 682fail_init:
 683        sfc_repr_proxy_rxq_stop(sa);
 684        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 685        return rc;
 686}
 687
 688static int
 689sfc_repr_proxy_mae_rule_insert(struct sfc_adapter *sa,
 690                               struct sfc_repr_proxy_port *port)
 691{
 692        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 693        efx_mport_sel_t mport_alias_selector;
 694        efx_mport_sel_t mport_vf_selector;
 695        struct sfc_mae_rule *mae_rule;
 696        int rc;
 697
 698        sfc_log_init(sa, "entry");
 699
 700        rc = efx_mae_mport_by_id(&port->egress_mport,
 701                                 &mport_vf_selector);
 702        if (rc != 0) {
 703                sfc_err(sa, "failed to get VF mport for repr %u",
 704                        port->repr_id);
 705                goto fail_get_vf;
 706        }
 707
 708        rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
 709        if (rc != 0) {
 710                sfc_err(sa, "failed to get mport selector for repr %u",
 711                        port->repr_id);
 712                goto fail_get_alias;
 713        }
 714
 715        rc = sfc_mae_rule_add_mport_match_deliver(sa, &mport_vf_selector,
 716                                                  &mport_alias_selector, -1,
 717                                                  &mae_rule);
 718        if (rc != 0) {
 719                sfc_err(sa, "failed to insert MAE rule for repr %u",
 720                        port->repr_id);
 721                goto fail_rule_add;
 722        }
 723
 724        port->mae_rule = mae_rule;
 725
 726        sfc_log_init(sa, "done");
 727
 728        return 0;
 729
 730fail_rule_add:
 731fail_get_alias:
 732fail_get_vf:
 733        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 734        return rc;
 735}
 736
 737static void
 738sfc_repr_proxy_mae_rule_remove(struct sfc_adapter *sa,
 739                               struct sfc_repr_proxy_port *port)
 740{
 741        struct sfc_mae_rule *mae_rule = port->mae_rule;
 742
 743        sfc_mae_rule_del(sa, mae_rule);
 744}
 745
 746static int
 747sfc_repr_proxy_mport_filter_insert(struct sfc_adapter *sa)
 748{
 749        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 750        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 751        struct sfc_rxq *rxq_ctrl;
 752        struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
 753        efx_mport_sel_t mport_alias_selector;
 754        static const efx_filter_match_flags_t flags[RTE_DIM(filter->specs)] = {
 755                EFX_FILTER_MATCH_UNKNOWN_UCAST_DST,
 756                EFX_FILTER_MATCH_UNKNOWN_MCAST_DST };
 757        unsigned int i;
 758        int rc;
 759
 760        sfc_log_init(sa, "entry");
 761
 762        if (sfc_repr_nb_rxq(sas) == 1) {
 763                rxq_ctrl = &sa->rxq_ctrl[rp->dp_rxq[0].sw_index];
 764        } else {
 765                sfc_err(sa, "multiple representor proxy RxQs not supported");
 766                rc = ENOTSUP;
 767                goto fail_multiple_queues;
 768        }
 769
 770        rc = efx_mae_mport_by_id(&rp->mport_alias, &mport_alias_selector);
 771        if (rc != 0) {
 772                sfc_err(sa, "failed to get repr proxy mport by ID");
 773                goto fail_get_selector;
 774        }
 775
 776        memset(filter->specs, 0, sizeof(filter->specs));
 777        for (i = 0; i < RTE_DIM(filter->specs); i++) {
 778                filter->specs[i].efs_priority = EFX_FILTER_PRI_MANUAL;
 779                filter->specs[i].efs_flags = EFX_FILTER_FLAG_RX;
 780                filter->specs[i].efs_dmaq_id = rxq_ctrl->hw_index;
 781                filter->specs[i].efs_match_flags = flags[i] |
 782                                EFX_FILTER_MATCH_MPORT;
 783                filter->specs[i].efs_ingress_mport = mport_alias_selector.sel;
 784
 785                rc = efx_filter_insert(sa->nic, &filter->specs[i]);
 786                if (rc != 0) {
 787                        sfc_err(sa, "failed to insert repr proxy filter");
 788                        goto fail_insert;
 789                }
 790        }
 791
 792        sfc_log_init(sa, "done");
 793
 794        return 0;
 795
 796fail_insert:
 797        while (i-- > 0)
 798                efx_filter_remove(sa->nic, &filter->specs[i]);
 799
 800fail_get_selector:
 801fail_multiple_queues:
 802        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 803        return rc;
 804}
 805
 806static void
 807sfc_repr_proxy_mport_filter_remove(struct sfc_adapter *sa)
 808{
 809        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 810        struct sfc_repr_proxy_filter *filter = &rp->mport_filter;
 811        unsigned int i;
 812
 813        for (i = 0; i < RTE_DIM(filter->specs); i++)
 814                efx_filter_remove(sa->nic, &filter->specs[i]);
 815}
 816
 817static int
 818sfc_repr_proxy_port_rule_insert(struct sfc_adapter *sa,
 819                                struct sfc_repr_proxy_port *port)
 820{
 821        int rc;
 822
 823        rc = sfc_repr_proxy_mae_rule_insert(sa, port);
 824        if (rc != 0)
 825                goto fail_mae_rule_insert;
 826
 827        return 0;
 828
 829fail_mae_rule_insert:
 830        return rc;
 831}
 832
 833static void
 834sfc_repr_proxy_port_rule_remove(struct sfc_adapter *sa,
 835                                struct sfc_repr_proxy_port *port)
 836{
 837        sfc_repr_proxy_mae_rule_remove(sa, port);
 838}
 839
 840static int
 841sfc_repr_proxy_ports_init(struct sfc_adapter *sa)
 842{
 843        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 844        int rc;
 845
 846        sfc_log_init(sa, "entry");
 847
 848        rc = efx_mcdi_mport_alloc_alias(sa->nic, &rp->mport_alias, NULL);
 849        if (rc != 0) {
 850                sfc_err(sa, "failed to alloc mport alias: %s",
 851                        rte_strerror(rc));
 852                goto fail_alloc_mport_alias;
 853        }
 854
 855        TAILQ_INIT(&rp->ports);
 856
 857        sfc_log_init(sa, "done");
 858
 859        return 0;
 860
 861fail_alloc_mport_alias:
 862
 863        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 864        return rc;
 865}
 866
 867void
 868sfc_repr_proxy_pre_detach(struct sfc_adapter *sa)
 869{
 870        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 871        bool close_ports[RTE_MAX_ETHPORTS] = {0};
 872        struct sfc_repr_proxy_port *port;
 873        unsigned int i;
 874
 875        SFC_ASSERT(!sfc_adapter_is_locked(sa));
 876
 877        sfc_adapter_lock(sa);
 878
 879        if (sfc_repr_available(sfc_sa2shared(sa))) {
 880                TAILQ_FOREACH(port, &rp->ports, entries)
 881                        close_ports[port->rte_port_id] = true;
 882        } else {
 883                sfc_log_init(sa, "representors not supported - skip");
 884        }
 885
 886        sfc_adapter_unlock(sa);
 887
 888        for (i = 0; i < RTE_DIM(close_ports); i++) {
 889                if (close_ports[i]) {
 890                        rte_eth_dev_stop(i);
 891                        rte_eth_dev_close(i);
 892                }
 893        }
 894}
 895
 896static void
 897sfc_repr_proxy_ports_fini(struct sfc_adapter *sa)
 898{
 899        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 900
 901        efx_mae_mport_free(sa->nic, &rp->mport_alias);
 902}
 903
 904int
 905sfc_repr_proxy_attach(struct sfc_adapter *sa)
 906{
 907        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
 908        struct sfc_repr_proxy *rp = &sa->repr_proxy;
 909        struct rte_service_spec service;
 910        uint32_t cid;
 911        uint32_t sid;
 912        int rc;
 913
 914        sfc_log_init(sa, "entry");
 915
 916        if (!sfc_repr_available(sas)) {
 917                sfc_log_init(sa, "representors not supported - skip");
 918                return 0;
 919        }
 920
 921        rc = sfc_repr_proxy_rxq_attach(sa);
 922        if (rc != 0)
 923                goto fail_rxq_attach;
 924
 925        rc = sfc_repr_proxy_txq_attach(sa);
 926        if (rc != 0)
 927                goto fail_txq_attach;
 928
 929        rc = sfc_repr_proxy_ports_init(sa);
 930        if (rc != 0)
 931                goto fail_ports_init;
 932
 933        cid = sfc_get_service_lcore(sa->socket_id);
 934        if (cid == RTE_MAX_LCORE && sa->socket_id != SOCKET_ID_ANY) {
 935                /* Warn and try to allocate on any NUMA node */
 936                sfc_warn(sa,
 937                        "repr proxy: unable to get service lcore at socket %d",
 938                        sa->socket_id);
 939
 940                cid = sfc_get_service_lcore(SOCKET_ID_ANY);
 941        }
 942        if (cid == RTE_MAX_LCORE) {
 943                rc = ENOTSUP;
 944                sfc_err(sa, "repr proxy: failed to get service lcore");
 945                goto fail_get_service_lcore;
 946        }
 947
 948        memset(&service, 0, sizeof(service));
 949        snprintf(service.name, sizeof(service.name),
 950                 "net_sfc_%hu_repr_proxy", sfc_sa2shared(sa)->port_id);
 951        service.socket_id = rte_lcore_to_socket_id(cid);
 952        service.callback = sfc_repr_proxy_routine;
 953        service.callback_userdata = rp;
 954
 955        rc = rte_service_component_register(&service, &sid);
 956        if (rc != 0) {
 957                rc = ENOEXEC;
 958                sfc_err(sa, "repr proxy: failed to register service component");
 959                goto fail_register;
 960        }
 961
 962        rc = rte_service_map_lcore_set(sid, cid, 1);
 963        if (rc != 0) {
 964                rc = -rc;
 965                sfc_err(sa, "repr proxy: failed to map lcore");
 966                goto fail_map_lcore;
 967        }
 968
 969        rp->service_core_id = cid;
 970        rp->service_id = sid;
 971
 972        sfc_log_init(sa, "done");
 973
 974        return 0;
 975
 976fail_map_lcore:
 977        rte_service_component_unregister(sid);
 978
 979fail_register:
 980        /*
 981         * No need to rollback service lcore get since
 982         * it just makes socket_id based search and remembers it.
 983         */
 984
 985fail_get_service_lcore:
 986        sfc_repr_proxy_ports_fini(sa);
 987
 988fail_ports_init:
 989        sfc_repr_proxy_txq_detach(sa);
 990
 991fail_txq_attach:
 992        sfc_repr_proxy_rxq_detach(sa);
 993
 994fail_rxq_attach:
 995        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
 996        return rc;
 997}
 998
 999void
1000sfc_repr_proxy_detach(struct sfc_adapter *sa)
1001{
1002        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1003        struct sfc_repr_proxy *rp = &sa->repr_proxy;
1004
1005        sfc_log_init(sa, "entry");
1006
1007        if (!sfc_repr_available(sas)) {
1008                sfc_log_init(sa, "representors not supported - skip");
1009                return;
1010        }
1011
1012        rte_service_map_lcore_set(rp->service_id, rp->service_core_id, 0);
1013        rte_service_component_unregister(rp->service_id);
1014        sfc_repr_proxy_ports_fini(sa);
1015        sfc_repr_proxy_rxq_detach(sa);
1016        sfc_repr_proxy_txq_detach(sa);
1017
1018        sfc_log_init(sa, "done");
1019}
1020
1021static int
1022sfc_repr_proxy_do_start_port(struct sfc_adapter *sa,
1023                           struct sfc_repr_proxy_port *port)
1024{
1025        struct sfc_repr_proxy *rp = &sa->repr_proxy;
1026        int rc;
1027
1028        rc = sfc_repr_proxy_port_rule_insert(sa, port);
1029        if (rc != 0)
1030                goto fail_filter_insert;
1031
1032        if (rp->started) {
1033                rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1034                                              SFC_REPR_PROXY_MBOX_START_PORT);
1035                if (rc != 0) {
1036                        sfc_err(sa, "failed to start proxy port %u",
1037                                port->repr_id);
1038                        goto fail_port_start;
1039                }
1040        } else {
1041                port->started = true;
1042        }
1043
1044        return 0;
1045
1046fail_port_start:
1047        sfc_repr_proxy_port_rule_remove(sa, port);
1048fail_filter_insert:
1049        sfc_err(sa, "%s() failed %s", __func__, rte_strerror(rc));
1050
1051        return rc;
1052}
1053
1054static int
1055sfc_repr_proxy_do_stop_port(struct sfc_adapter *sa,
1056                          struct sfc_repr_proxy_port *port)
1057
1058{
1059        struct sfc_repr_proxy *rp = &sa->repr_proxy;
1060        int rc;
1061
1062        if (rp->started) {
1063                rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1064                                              SFC_REPR_PROXY_MBOX_STOP_PORT);
1065                if (rc != 0) {
1066                        sfc_err(sa, "failed to stop proxy port %u: %s",
1067                                port->repr_id, rte_strerror(rc));
1068                        return rc;
1069                }
1070        } else {
1071                port->started = false;
1072        }
1073
1074        sfc_repr_proxy_port_rule_remove(sa, port);
1075
1076        return 0;
1077}
1078
1079static bool
1080sfc_repr_proxy_port_enabled(struct sfc_repr_proxy_port *port)
1081{
1082        return port->rte_port_id != RTE_MAX_ETHPORTS && port->enabled;
1083}
1084
1085static bool
1086sfc_repr_proxy_ports_disabled(struct sfc_repr_proxy *rp)
1087{
1088        struct sfc_repr_proxy_port *port;
1089
1090        TAILQ_FOREACH(port, &rp->ports, entries) {
1091                if (sfc_repr_proxy_port_enabled(port))
1092                        return false;
1093        }
1094
1095        return true;
1096}
1097
1098int
1099sfc_repr_proxy_start(struct sfc_adapter *sa)
1100{
1101        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1102        struct sfc_repr_proxy *rp = &sa->repr_proxy;
1103        struct sfc_repr_proxy_port *last_port = NULL;
1104        struct sfc_repr_proxy_port *port;
1105        int rc;
1106
1107        sfc_log_init(sa, "entry");
1108
1109        /* Representor proxy is not started when no representors are started */
1110        if (!sfc_repr_available(sas)) {
1111                sfc_log_init(sa, "representors not supported - skip");
1112                return 0;
1113        }
1114
1115        if (sfc_repr_proxy_ports_disabled(rp)) {
1116                sfc_log_init(sa, "no started representor ports - skip");
1117                return 0;
1118        }
1119
1120        rc = sfc_repr_proxy_rxq_start(sa);
1121        if (rc != 0)
1122                goto fail_rxq_start;
1123
1124        rc = sfc_repr_proxy_txq_start(sa);
1125        if (rc != 0)
1126                goto fail_txq_start;
1127
1128        rp->nb_txq = sfc_repr_nb_txq(sas);
1129        rp->nb_rxq = sfc_repr_nb_rxq(sas);
1130
1131        /* Service core may be in "stopped" state, start it */
1132        rc = rte_service_lcore_start(rp->service_core_id);
1133        if (rc != 0 && rc != -EALREADY) {
1134                rc = -rc;
1135                sfc_err(sa, "failed to start service core for %s: %s",
1136                        rte_service_get_name(rp->service_id),
1137                        rte_strerror(rc));
1138                goto fail_start_core;
1139        }
1140
1141        /* Run the service */
1142        rc = rte_service_component_runstate_set(rp->service_id, 1);
1143        if (rc < 0) {
1144                rc = -rc;
1145                sfc_err(sa, "failed to run %s component: %s",
1146                        rte_service_get_name(rp->service_id),
1147                        rte_strerror(rc));
1148                goto fail_component_runstate_set;
1149        }
1150        rc = rte_service_runstate_set(rp->service_id, 1);
1151        if (rc < 0) {
1152                rc = -rc;
1153                sfc_err(sa, "failed to run %s: %s",
1154                        rte_service_get_name(rp->service_id),
1155                        rte_strerror(rc));
1156                goto fail_runstate_set;
1157        }
1158
1159        TAILQ_FOREACH(port, &rp->ports, entries) {
1160                if (sfc_repr_proxy_port_enabled(port)) {
1161                        rc = sfc_repr_proxy_do_start_port(sa, port);
1162                        if (rc != 0)
1163                                goto fail_start_id;
1164
1165                        last_port = port;
1166                }
1167        }
1168
1169        rc = sfc_repr_proxy_mport_filter_insert(sa);
1170        if (rc != 0)
1171                goto fail_mport_filter_insert;
1172
1173        rp->started = true;
1174
1175        sfc_log_init(sa, "done");
1176
1177        return 0;
1178
1179fail_mport_filter_insert:
1180fail_start_id:
1181        if (last_port != NULL) {
1182                TAILQ_FOREACH(port, &rp->ports, entries) {
1183                        if (sfc_repr_proxy_port_enabled(port)) {
1184                                (void)sfc_repr_proxy_do_stop_port(sa, port);
1185                                if (port == last_port)
1186                                        break;
1187                        }
1188                }
1189        }
1190
1191        rte_service_runstate_set(rp->service_id, 0);
1192
1193fail_runstate_set:
1194        rte_service_component_runstate_set(rp->service_id, 0);
1195
1196fail_component_runstate_set:
1197        /* Service lcore may be shared and we never stop it */
1198
1199fail_start_core:
1200        sfc_repr_proxy_txq_stop(sa);
1201
1202fail_txq_start:
1203        sfc_repr_proxy_rxq_stop(sa);
1204
1205fail_rxq_start:
1206        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1207        return rc;
1208}
1209
1210void
1211sfc_repr_proxy_stop(struct sfc_adapter *sa)
1212{
1213        struct sfc_adapter_shared * const sas = sfc_sa2shared(sa);
1214        struct sfc_repr_proxy *rp = &sa->repr_proxy;
1215        struct sfc_repr_proxy_port *port;
1216        const unsigned int wait_ms_total =
1217                SFC_REPR_PROXY_ROUTINE_TERMINATE_TIMEOUT_MS;
1218        unsigned int i;
1219        int rc;
1220
1221        sfc_log_init(sa, "entry");
1222
1223        if (!sfc_repr_available(sas)) {
1224                sfc_log_init(sa, "representors not supported - skip");
1225                return;
1226        }
1227
1228        if (sfc_repr_proxy_ports_disabled(rp)) {
1229                sfc_log_init(sa, "no started representor ports - skip");
1230                return;
1231        }
1232
1233        TAILQ_FOREACH(port, &rp->ports, entries) {
1234                if (sfc_repr_proxy_port_enabled(port)) {
1235                        rc = sfc_repr_proxy_do_stop_port(sa, port);
1236                        if (rc != 0) {
1237                                sfc_err(sa,
1238                                        "failed to stop representor proxy port %u: %s",
1239                                        port->repr_id, rte_strerror(rc));
1240                        }
1241                }
1242        }
1243
1244        sfc_repr_proxy_mport_filter_remove(sa);
1245
1246        rc = rte_service_runstate_set(rp->service_id, 0);
1247        if (rc < 0) {
1248                sfc_err(sa, "failed to stop %s: %s",
1249                        rte_service_get_name(rp->service_id),
1250                        rte_strerror(-rc));
1251        }
1252
1253        rc = rte_service_component_runstate_set(rp->service_id, 0);
1254        if (rc < 0) {
1255                sfc_err(sa, "failed to stop %s component: %s",
1256                        rte_service_get_name(rp->service_id),
1257                        rte_strerror(-rc));
1258        }
1259
1260        /* Service lcore may be shared and we never stop it */
1261
1262        /*
1263         * Wait for the representor proxy routine to finish the last iteration.
1264         * Give up on timeout.
1265         */
1266        for (i = 0; i < wait_ms_total; i++) {
1267                if (rte_service_may_be_active(rp->service_id) == 0)
1268                        break;
1269
1270                rte_delay_ms(1);
1271        }
1272
1273        sfc_repr_proxy_rxq_stop(sa);
1274        sfc_repr_proxy_txq_stop(sa);
1275
1276        rp->started = false;
1277
1278        sfc_log_init(sa, "done");
1279}
1280
1281int
1282sfc_repr_proxy_add_port(uint16_t pf_port_id, uint16_t repr_id,
1283                        uint16_t rte_port_id, const efx_mport_sel_t *mport_sel)
1284{
1285        struct sfc_repr_proxy_port *port;
1286        struct sfc_repr_proxy *rp;
1287        struct sfc_adapter *sa;
1288        int rc;
1289
1290        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1291        rp = sfc_repr_proxy_by_adapter(sa);
1292
1293        sfc_log_init(sa, "entry");
1294        TAILQ_FOREACH(port, &rp->ports, entries) {
1295                if (port->rte_port_id == rte_port_id) {
1296                        rc = EEXIST;
1297                        sfc_err(sa, "%s() failed: port exists", __func__);
1298                        goto fail_port_exists;
1299                }
1300        }
1301
1302        port = rte_zmalloc("sfc-repr-proxy-port", sizeof(*port),
1303                           sa->socket_id);
1304        if (port == NULL) {
1305                rc = ENOMEM;
1306                sfc_err(sa, "failed to alloc memory for proxy port");
1307                goto fail_alloc_port;
1308        }
1309
1310        rc = efx_mae_mport_id_by_selector(sa->nic, mport_sel,
1311                                          &port->egress_mport);
1312        if (rc != 0) {
1313                sfc_err(sa,
1314                        "failed get MAE mport id by selector (repr_id %u): %s",
1315                        repr_id, rte_strerror(rc));
1316                goto fail_mport_id;
1317        }
1318
1319        port->rte_port_id = rte_port_id;
1320        port->repr_id = repr_id;
1321
1322        if (rp->started) {
1323                rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1324                                              SFC_REPR_PROXY_MBOX_ADD_PORT);
1325                if (rc != 0) {
1326                        sfc_err(sa, "failed to add proxy port %u",
1327                                port->repr_id);
1328                        goto fail_port_add;
1329                }
1330        } else {
1331                TAILQ_INSERT_TAIL(&rp->ports, port, entries);
1332        }
1333
1334        sfc_log_init(sa, "done");
1335        sfc_put_adapter(sa);
1336
1337        return 0;
1338
1339fail_port_add:
1340fail_mport_id:
1341        rte_free(port);
1342fail_alloc_port:
1343fail_port_exists:
1344        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1345        sfc_put_adapter(sa);
1346
1347        return rc;
1348}
1349
1350int
1351sfc_repr_proxy_del_port(uint16_t pf_port_id, uint16_t repr_id)
1352{
1353        struct sfc_repr_proxy_port *port;
1354        struct sfc_repr_proxy *rp;
1355        struct sfc_adapter *sa;
1356        int rc;
1357
1358        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1359        rp = sfc_repr_proxy_by_adapter(sa);
1360
1361        sfc_log_init(sa, "entry");
1362
1363        port = sfc_repr_proxy_find_port(rp, repr_id);
1364        if (port == NULL) {
1365                sfc_err(sa, "failed: no such port");
1366                rc = ENOENT;
1367                goto fail_no_port;
1368        }
1369
1370        if (rp->started) {
1371                rc = sfc_repr_proxy_mbox_send(&rp->mbox, port,
1372                                              SFC_REPR_PROXY_MBOX_DEL_PORT);
1373                if (rc != 0) {
1374                        sfc_err(sa, "failed to remove proxy port %u",
1375                                port->repr_id);
1376                        goto fail_port_remove;
1377                }
1378        } else {
1379                TAILQ_REMOVE(&rp->ports, port, entries);
1380        }
1381
1382        rte_free(port);
1383
1384        sfc_log_init(sa, "done");
1385
1386        sfc_put_adapter(sa);
1387
1388        return 0;
1389
1390fail_port_remove:
1391fail_no_port:
1392        sfc_log_init(sa, "failed: %s", rte_strerror(rc));
1393        sfc_put_adapter(sa);
1394
1395        return rc;
1396}
1397
1398int
1399sfc_repr_proxy_add_rxq(uint16_t pf_port_id, uint16_t repr_id,
1400                       uint16_t queue_id, struct rte_ring *rx_ring,
1401                       struct rte_mempool *mp)
1402{
1403        struct sfc_repr_proxy_port *port;
1404        struct sfc_repr_proxy_rxq *rxq;
1405        struct sfc_repr_proxy *rp;
1406        struct sfc_adapter *sa;
1407
1408        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1409        rp = sfc_repr_proxy_by_adapter(sa);
1410
1411        sfc_log_init(sa, "entry");
1412
1413        port = sfc_repr_proxy_find_port(rp, repr_id);
1414        if (port == NULL) {
1415                sfc_err(sa, "%s() failed: no such port", __func__);
1416                sfc_put_adapter(sa);
1417                return ENOENT;
1418        }
1419
1420        rxq = &port->rxq[queue_id];
1421        if (rp->dp_rxq[queue_id].mp != NULL && rp->dp_rxq[queue_id].mp != mp) {
1422                sfc_err(sa, "multiple mempools per queue are not supported");
1423                sfc_put_adapter(sa);
1424                return ENOTSUP;
1425        }
1426
1427        rxq->ring = rx_ring;
1428        rxq->mb_pool = mp;
1429        rp->dp_rxq[queue_id].mp = mp;
1430        rp->dp_rxq[queue_id].ref_count++;
1431
1432        sfc_log_init(sa, "done");
1433        sfc_put_adapter(sa);
1434
1435        return 0;
1436}
1437
1438void
1439sfc_repr_proxy_del_rxq(uint16_t pf_port_id, uint16_t repr_id,
1440                       uint16_t queue_id)
1441{
1442        struct sfc_repr_proxy_port *port;
1443        struct sfc_repr_proxy_rxq *rxq;
1444        struct sfc_repr_proxy *rp;
1445        struct sfc_adapter *sa;
1446
1447        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1448        rp = sfc_repr_proxy_by_adapter(sa);
1449
1450        sfc_log_init(sa, "entry");
1451
1452        port = sfc_repr_proxy_find_port(rp, repr_id);
1453        if (port == NULL) {
1454                sfc_err(sa, "%s() failed: no such port", __func__);
1455                sfc_put_adapter(sa);
1456                return;
1457        }
1458
1459        rxq = &port->rxq[queue_id];
1460
1461        rxq->ring = NULL;
1462        rxq->mb_pool = NULL;
1463        rp->dp_rxq[queue_id].ref_count--;
1464        if (rp->dp_rxq[queue_id].ref_count == 0)
1465                rp->dp_rxq[queue_id].mp = NULL;
1466
1467        sfc_log_init(sa, "done");
1468        sfc_put_adapter(sa);
1469}
1470
1471int
1472sfc_repr_proxy_add_txq(uint16_t pf_port_id, uint16_t repr_id,
1473                       uint16_t queue_id, struct rte_ring *tx_ring,
1474                       efx_mport_id_t *egress_mport)
1475{
1476        struct sfc_repr_proxy_port *port;
1477        struct sfc_repr_proxy_txq *txq;
1478        struct sfc_repr_proxy *rp;
1479        struct sfc_adapter *sa;
1480
1481        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1482        rp = sfc_repr_proxy_by_adapter(sa);
1483
1484        sfc_log_init(sa, "entry");
1485
1486        port = sfc_repr_proxy_find_port(rp, repr_id);
1487        if (port == NULL) {
1488                sfc_err(sa, "%s() failed: no such port", __func__);
1489                sfc_put_adapter(sa);
1490                return ENOENT;
1491        }
1492
1493        txq = &port->txq[queue_id];
1494
1495        txq->ring = tx_ring;
1496
1497        *egress_mport = port->egress_mport;
1498
1499        sfc_log_init(sa, "done");
1500        sfc_put_adapter(sa);
1501
1502        return 0;
1503}
1504
1505void
1506sfc_repr_proxy_del_txq(uint16_t pf_port_id, uint16_t repr_id,
1507                       uint16_t queue_id)
1508{
1509        struct sfc_repr_proxy_port *port;
1510        struct sfc_repr_proxy_txq *txq;
1511        struct sfc_repr_proxy *rp;
1512        struct sfc_adapter *sa;
1513
1514        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1515        rp = sfc_repr_proxy_by_adapter(sa);
1516
1517        sfc_log_init(sa, "entry");
1518
1519        port = sfc_repr_proxy_find_port(rp, repr_id);
1520        if (port == NULL) {
1521                sfc_err(sa, "%s() failed: no such port", __func__);
1522                sfc_put_adapter(sa);
1523                return;
1524        }
1525
1526        txq = &port->txq[queue_id];
1527
1528        txq->ring = NULL;
1529
1530        sfc_log_init(sa, "done");
1531        sfc_put_adapter(sa);
1532}
1533
1534int
1535sfc_repr_proxy_start_repr(uint16_t pf_port_id, uint16_t repr_id)
1536{
1537        bool proxy_start_required = false;
1538        struct sfc_repr_proxy_port *port;
1539        struct sfc_repr_proxy *rp;
1540        struct sfc_adapter *sa;
1541        int rc;
1542
1543        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1544        rp = sfc_repr_proxy_by_adapter(sa);
1545
1546        sfc_log_init(sa, "entry");
1547
1548        port = sfc_repr_proxy_find_port(rp, repr_id);
1549        if (port == NULL) {
1550                sfc_err(sa, "%s() failed: no such port", __func__);
1551                rc = ENOENT;
1552                goto fail_not_found;
1553        }
1554
1555        if (port->enabled) {
1556                rc = EALREADY;
1557                sfc_err(sa, "failed: repr %u proxy port already started",
1558                        repr_id);
1559                goto fail_already_started;
1560        }
1561
1562        if (sa->state == SFC_ETHDEV_STARTED) {
1563                if (sfc_repr_proxy_ports_disabled(rp)) {
1564                        proxy_start_required = true;
1565                } else {
1566                        rc = sfc_repr_proxy_do_start_port(sa, port);
1567                        if (rc != 0) {
1568                                sfc_err(sa,
1569                                        "failed to start repr %u proxy port",
1570                                        repr_id);
1571                                goto fail_start_id;
1572                        }
1573                }
1574        }
1575
1576        port->enabled = true;
1577
1578        if (proxy_start_required) {
1579                rc = sfc_repr_proxy_start(sa);
1580                if (rc != 0) {
1581                        sfc_err(sa, "failed to start proxy");
1582                        goto fail_proxy_start;
1583                }
1584        }
1585
1586        sfc_log_init(sa, "done");
1587        sfc_put_adapter(sa);
1588
1589        return 0;
1590
1591fail_proxy_start:
1592        port->enabled = false;
1593
1594fail_start_id:
1595fail_already_started:
1596fail_not_found:
1597        sfc_err(sa, "failed to start repr %u proxy port: %s", repr_id,
1598                rte_strerror(rc));
1599        sfc_put_adapter(sa);
1600
1601        return rc;
1602}
1603
1604int
1605sfc_repr_proxy_stop_repr(uint16_t pf_port_id, uint16_t repr_id)
1606{
1607        struct sfc_repr_proxy_port *port;
1608        struct sfc_repr_proxy_port *p;
1609        struct sfc_repr_proxy *rp;
1610        struct sfc_adapter *sa;
1611        int rc;
1612
1613        sa = sfc_get_adapter_by_pf_port_id(pf_port_id);
1614        rp = sfc_repr_proxy_by_adapter(sa);
1615
1616        sfc_log_init(sa, "entry");
1617
1618        port = sfc_repr_proxy_find_port(rp, repr_id);
1619        if (port == NULL) {
1620                sfc_err(sa, "%s() failed: no such port", __func__);
1621                sfc_put_adapter(sa);
1622                return ENOENT;
1623        }
1624
1625        if (!port->enabled) {
1626                sfc_log_init(sa, "repr %u proxy port is not started - skip",
1627                             repr_id);
1628                sfc_put_adapter(sa);
1629                return 0;
1630        }
1631
1632        if (sa->state == SFC_ETHDEV_STARTED) {
1633                bool last_enabled = true;
1634
1635                TAILQ_FOREACH(p, &rp->ports, entries) {
1636                        if (p == port)
1637                                continue;
1638
1639                        if (sfc_repr_proxy_port_enabled(p)) {
1640                                last_enabled = false;
1641                                break;
1642                        }
1643                }
1644
1645                rc = 0;
1646                if (last_enabled)
1647                        sfc_repr_proxy_stop(sa);
1648                else
1649                        rc = sfc_repr_proxy_do_stop_port(sa, port);
1650
1651                if (rc != 0) {
1652                        sfc_err(sa,
1653                                "failed to stop representor proxy TxQ %u: %s",
1654                                repr_id, rte_strerror(rc));
1655                        sfc_put_adapter(sa);
1656                        return rc;
1657                }
1658        }
1659
1660        port->enabled = false;
1661
1662        sfc_log_init(sa, "done");
1663        sfc_put_adapter(sa);
1664
1665        return 0;
1666}
1667