From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id CF72E43036; Fri, 11 Aug 2023 18:35:45 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 9D2A94327B; Fri, 11 Aug 2023 18:35:16 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 3489043273 for ; Fri, 11 Aug 2023 18:35:14 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 37BEGHYK021465 for ; Fri, 11 Aug 2023 09:35:13 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=pfpt0220; bh=HPBu6oQAif/lUxtbnZ7C5yu6r6XRwh43Uo48qhby5PY=; b=M1000LfmlA2Lu0dVPFJDbHf8g+eH+ud8BmojR1hkNIcxb6QJ7/oKcPq8DfWWiefygd2j PXOokNwinJC09bDYS0PRz8CI9+7UYWo0t2ojc5z1OGRyI/KvhBU6aciNZfp9KYw0E522 Ec6XgQXsFIYJeBT9fakb/+L8uIx9vhiwzj8mLWdzw+1Y9a/0wx+PjYQZ8W5KY27EtWBI ecF7cHm11B1xNLuLVb6TnL6tPUM/oo5ckMhMrz7SBc/61HpKNHMxqSPZme1H/eg2kezx wjlxZowLwODW8WkFVigTGKcPyrAjyLOFIMZCsljsV2dUvzhISMcnKFrUpm7qUGu6TsFw ew== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3sd8ya2quj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT) for ; Fri, 11 Aug 2023 09:35:13 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Fri, 11 Aug 2023 09:35:11 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Fri, 11 Aug 2023 09:35:11 -0700 Received: from localhost.localdomain (unknown [10.29.52.211]) by maili.marvell.com (Postfix) with ESMTP id 9A1973F7055; Fri, 11 Aug 2023 09:35:08 -0700 (PDT) From: Harman Kalra To: , Nithin Dabilpuram , "Kiran Kumar K" , Sunil Kumar Kori , Satha Rao CC: , Harman Kalra Subject: [PATCH 6/9] net/cnxk: representor ethdev ops Date: Fri, 11 Aug 2023 22:04:16 +0530 Message-ID: <20230811163419.165790-7-hkalra@marvell.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20230811163419.165790-1-hkalra@marvell.com> References: <20230811163419.165790-1-hkalra@marvell.com> MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-ORIG-GUID: GY4kkK-xGf3KNFX3VkWJh8jJdHjsC0B6 X-Proofpoint-GUID: GY4kkK-xGf3KNFX3VkWJh8jJdHjsC0B6 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.267,Aquarius:18.0.957,Hydra:6.0.591,FMLib:17.11.176.26 definitions=2023-08-11_08,2023-08-10_01,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Implementing ethernet device operation callbacks for port representors PMD Signed-off-by: Harman Kalra --- drivers/net/cnxk/cnxk_rep.c | 62 +-- drivers/net/cnxk/cnxk_rep.h | 36 ++ drivers/net/cnxk/cnxk_rep_msg.h | 15 + drivers/net/cnxk/cnxk_rep_ops.c | 655 ++++++++++++++++++++++++++++++-- 4 files changed, 713 insertions(+), 55 deletions(-) diff --git a/drivers/net/cnxk/cnxk_rep.c b/drivers/net/cnxk/cnxk_rep.c index e6f5790adc..5ee7e93ab9 100644 --- a/drivers/net/cnxk/cnxk_rep.c +++ b/drivers/net/cnxk/cnxk_rep.c @@ -13,6 +13,9 @@ struct eth_dev_ops cnxk_rep_dev_ops = { .rx_queue_release = cnxk_rep_rx_queue_release, .tx_queue_setup = cnxk_rep_tx_queue_setup, .tx_queue_release = cnxk_rep_tx_queue_release, + .promiscuous_enable = cnxk_rep_promiscuous_enable, + .promiscuous_disable = cnxk_rep_promiscuous_disable, + .mac_addr_set = cnxk_rep_mac_addr_set, .link_update = cnxk_rep_link_update, .dev_close = cnxk_rep_dev_close, .dev_stop = cnxk_rep_dev_stop, @@ -24,14 +27,36 @@ struct eth_dev_ops cnxk_rep_dev_ops = { int cnxk_rep_dev_uninit(struct rte_eth_dev *ethdev) { + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + + rep_xport_vdev_cfg = mz->addr; plt_rep_dbg("Representor port:%d uninit", ethdev->data->port_id); rte_free(ethdev->data->mac_addrs); ethdev->data->mac_addrs = NULL; + rep_xport_vdev_cfg->nb_rep_ports--; + /* Once all representors are closed, cleanup rep base vdev config */ + if (!rep_xport_vdev_cfg->nb_rep_ports) { + plt_free(rep_xport_vdev_cfg->q_bmap_mem); + plt_free(rep_xport_vdev_cfg->mdevinfo); + plt_memzone_free(mz); + } + return 0; +fail: + return rte_errno; } int @@ -121,26 +146,6 @@ cnxk_init_rep_internal(struct cnxk_eth_dev *pf_dev) return rc; } -static uint16_t -cnxk_rep_tx_burst(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) -{ - PLT_SET_USED(tx_queue); - PLT_SET_USED(tx_pkts); - PLT_SET_USED(nb_pkts); - - return 0; -} - -static uint16_t -cnxk_rep_rx_burst(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) -{ - PLT_SET_USED(rx_queue); - PLT_SET_USED(rx_pkts); - PLT_SET_USED(nb_pkts); - - return 0; -} - static int cnxk_rep_dev_init(struct rte_eth_dev *eth_dev, void *params) { @@ -152,6 +157,11 @@ cnxk_rep_dev_init(struct rte_eth_dev *eth_dev, void *params) rep_dev->vf_id = rep_params->vf_id; rep_dev->switch_domain_id = rep_params->switch_domain_id; rep_dev->parent_dev = rep_params->parent_dev; + rep_dev->u.rxq = UINT16_MAX; + rep_dev->u.txq = UINT16_MAX; + + pf_dev = cnxk_eth_pmd_priv(rep_dev->parent_dev); + rep_dev->rep_xport_vdev = pf_dev->rep_xport_vdev; eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR; eth_dev->data->representor_id = rep_params->vf_id; @@ -170,11 +180,10 @@ cnxk_rep_dev_init(struct rte_eth_dev *eth_dev, void *params) eth_dev->dev_ops = &cnxk_rep_dev_ops; /* Rx/Tx functions stubs to avoid crashing */ - eth_dev->rx_pkt_burst = cnxk_rep_rx_burst; - eth_dev->tx_pkt_burst = cnxk_rep_tx_burst; + eth_dev->rx_pkt_burst = cnxk_rep_rx_burst_dummy; + eth_dev->tx_pkt_burst = cnxk_rep_tx_burst_dummy; /* Link state. Inherited from PF */ - pf_dev = cnxk_eth_pmd_priv(rep_dev->parent_dev); link = &pf_dev->eth_dev->data->dev_link; eth_dev->data->dev_link.link_speed = link->link_speed; @@ -325,13 +334,6 @@ cnxk_rep_dev_probe(struct rte_pci_device *pci_dev, struct rte_eth_dev *pf_ethdev goto err; } - /* Launch a thread to handle control messages */ - rc = cnxk_rep_control_thread_launch(pf_dev); - if (rc) { - plt_err("Failed to launch message ctrl thread"); - goto err; - } - return 0; err: return rc; diff --git a/drivers/net/cnxk/cnxk_rep.h b/drivers/net/cnxk/cnxk_rep.h index 8825fa1cf2..2b6403f003 100644 --- a/drivers/net/cnxk/cnxk_rep.h +++ b/drivers/net/cnxk/cnxk_rep.h @@ -6,6 +6,7 @@ #ifndef __CNXK_REP_H__ #define __CNXK_REP_H__ +#define CNXK_REP_XPORT_VDEV_CFG_MZ "rep_xport_vdev_cfg" #define CNXK_REP_XPORT_VDEV_DEVARGS "role=server" #define CNXK_REP_XPORT_VDEV_NAME "net_memif" #define CNXK_REP_VDEV_CTRL_QUEUE 0 @@ -14,6 +15,18 @@ /* Common ethdev ops */ extern struct eth_dev_ops cnxk_rep_dev_ops; +/* Representor base device configurations */ +typedef struct rep_xport_vdev_cfg_s { + struct plt_bitmap *q_map; + void *q_bmap_mem; + uint8_t nb_rep_ports; + uint8_t nb_rep_started; + struct rte_mempool *ctrl_chan_pool; + struct rte_eth_dev_info *mdevinfo; + bool rep_xport_configured; +} rep_xport_vdev_cfg_t; + +/* Representor port configurations */ struct cnxk_rep_dev { uint16_t vf_id; uint16_t switch_domain_id; @@ -22,15 +35,33 @@ struct cnxk_rep_dev { uint16_t rep_xport_vdev; bool is_vf_active; uint16_t pf_func; + union { + uint16_t rxq; + uint16_t txq; + uint16_t rep_portid; + } u; uint8_t mac_addr[RTE_ETHER_ADDR_LEN]; }; +/* Inline functions */ static inline struct cnxk_rep_dev * cnxk_rep_pmd_priv(const struct rte_eth_dev *eth_dev) { return eth_dev->data->dev_private; } +static inline struct rte_eth_dev * +cnxk_rep_xport_eth_dev(uint16_t portid) +{ + if (!rte_eth_dev_is_valid_port(portid)) { + plt_err("Invalid port_id=%u", portid); + return NULL; + } + + return &rte_eth_devices[portid]; +} + +/* Prototypes */ int cnxk_rep_dev_probe(struct rte_pci_device *pci_dev, struct rte_eth_dev *pf_ethdev, struct rte_eth_devargs *eth_da); int cnxk_rep_dev_remove(struct rte_eth_dev *pf_ethdev); @@ -52,5 +83,10 @@ int cnxk_rep_dev_close(struct rte_eth_dev *eth_dev); int cnxk_rep_stats_get(struct rte_eth_dev *eth_dev, struct rte_eth_stats *stats); int cnxk_rep_stats_reset(struct rte_eth_dev *eth_dev); int cnxk_rep_flow_ops_get(struct rte_eth_dev *ethdev, const struct rte_flow_ops **ops); +int cnxk_rep_promiscuous_enable(struct rte_eth_dev *ethdev); +int cnxk_rep_promiscuous_disable(struct rte_eth_dev *ethdev); +int cnxk_rep_mac_addr_set(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr); +uint16_t cnxk_rep_tx_burst_dummy(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts); +uint16_t cnxk_rep_rx_burst_dummy(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); #endif /* __CNXK_REP_H__ */ diff --git a/drivers/net/cnxk/cnxk_rep_msg.h b/drivers/net/cnxk/cnxk_rep_msg.h index a28c63f762..554122d7f8 100644 --- a/drivers/net/cnxk/cnxk_rep_msg.h +++ b/drivers/net/cnxk/cnxk_rep_msg.h @@ -19,6 +19,10 @@ typedef enum CNXK_REP_MSG { CNXK_REP_MSG_READY = 0, CNXK_REP_MSG_ACK, CNXK_REP_MSG_EXIT, + /* Ethernet operation msgs */ + CNXK_REP_MSG_ETH_SET_MAC, + CNXK_REP_MSG_ETH_STATS_GET, + CNXK_REP_MSG_ETH_STATS_CLEAR, /* End of messaging sequence */ CNXK_REP_MSG_END, } cnxk_rep_msg_t; @@ -64,6 +68,17 @@ typedef struct cnxk_rep_msg_exit_data { uint8_t val; } __rte_packed cnxk_rep_msg_exit_data_t; +/* Ethernet op - set mac */ +typedef struct cnxk_rep_msg_eth_mac_set_meta { + uint16_t portid; + uint8_t addr_bytes[RTE_ETHER_ADDR_LEN]; +} __rte_packed cnxk_rep_msg_eth_set_mac_meta_t; + +/* Ethernet op - get/clear stats */ +typedef struct cnxk_rep_msg_eth_stats_meta { + uint16_t portid; +} __rte_packed cnxk_rep_msg_eth_stats_meta_t; + void cnxk_rep_msg_populate_command(void *buffer, uint32_t *length, cnxk_rep_msg_t type, uint32_t size); void cnxk_rep_msg_populate_command_meta(void *buffer, uint32_t *length, void *msg_meta, uint32_t sz, diff --git a/drivers/net/cnxk/cnxk_rep_ops.c b/drivers/net/cnxk/cnxk_rep_ops.c index 3f1aab077b..022a5137df 100644 --- a/drivers/net/cnxk/cnxk_rep_ops.c +++ b/drivers/net/cnxk/cnxk_rep_ops.c @@ -3,6 +3,54 @@ */ #include +#include + +#define MEMPOOL_CACHE_SIZE 256 +#define TX_DESC_PER_QUEUE 512 +#define RX_DESC_PER_QUEUE 256 +#define NB_REP_VDEV_MBUF 1024 + +static uint16_t +cnxk_rep_tx_burst(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) +{ + struct cnxk_rep_dev *rep_dev = tx_queue; + + nb_pkts = rte_eth_tx_burst(rep_dev->rep_xport_vdev, rep_dev->u.txq, tx_pkts, nb_pkts); + + return nb_pkts; +} + +static uint16_t +cnxk_rep_rx_burst(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) +{ + struct cnxk_rep_dev *rep_dev = rx_queue; + + nb_pkts = rte_eth_rx_burst(rep_dev->rep_xport_vdev, rep_dev->u.txq, rx_pkts, 32); + if (nb_pkts == 0) + return 0; + + return nb_pkts; +} + +uint16_t +cnxk_rep_tx_burst_dummy(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts) +{ + PLT_SET_USED(tx_queue); + PLT_SET_USED(tx_pkts); + PLT_SET_USED(nb_pkts); + + return 0; +} + +uint16_t +cnxk_rep_rx_burst_dummy(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) +{ + PLT_SET_USED(rx_queue); + PLT_SET_USED(rx_pkts); + PLT_SET_USED(nb_pkts); + + return 0; +} int cnxk_rep_link_update(struct rte_eth_dev *ethdev, int wait_to_complete) @@ -13,39 +61,379 @@ cnxk_rep_link_update(struct rte_eth_dev *ethdev, int wait_to_complete) } int -cnxk_rep_dev_info_get(struct rte_eth_dev *ethdev, struct rte_eth_dev_info *devinfo) +cnxk_rep_dev_info_get(struct rte_eth_dev *ethdev, struct rte_eth_dev_info *dev_info) { - PLT_SET_USED(ethdev); - PLT_SET_USED(devinfo); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + struct rte_eth_dev_info mdevinfo; + const struct plt_memzone *mz; + int rc = 0; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + mz = plt_memzone_reserve_cache_align(CNXK_REP_XPORT_VDEV_CFG_MZ, + sizeof(rep_xport_vdev_cfg_t)); + if (!mz) { + plt_err("Failed to reserve a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + } + + rep_xport_vdev_cfg = mz->addr; + /* Get the rep base vdev devinfo */ + if (!rep_xport_vdev_cfg->mdevinfo) { + rc = rte_eth_dev_info_get(rep_dev->rep_xport_vdev, &mdevinfo); + if (rc) { + plt_err("Failed to get rep_xport port dev info, err %d", rc); + goto fail; + } + rep_xport_vdev_cfg->mdevinfo = plt_zmalloc(sizeof(struct rte_eth_dev_info), 0); + if (!rep_xport_vdev_cfg->mdevinfo) { + plt_err("Failed to alloc memory for dev info"); + goto fail; + } + rte_memcpy(rep_xport_vdev_cfg->mdevinfo, &mdevinfo, + sizeof(struct rte_eth_dev_info)); + } + + /* Use rep_xport device info */ + dev_info->max_mac_addrs = rep_xport_vdev_cfg->mdevinfo->max_mac_addrs; + dev_info->max_rx_pktlen = rep_xport_vdev_cfg->mdevinfo->max_rx_pktlen; + dev_info->min_rx_bufsize = rep_xport_vdev_cfg->mdevinfo->min_rx_bufsize; + dev_info->tx_offload_capa = rep_xport_vdev_cfg->mdevinfo->tx_offload_capa; + + /* For the sake of symmetry, max_rx_queues = max_tx_queues */ + dev_info->max_rx_queues = 1; + dev_info->max_tx_queues = 1; + + /* MTU specifics */ + dev_info->max_mtu = rep_xport_vdev_cfg->mdevinfo->max_mtu; + dev_info->min_mtu = rep_xport_vdev_cfg->mdevinfo->min_mtu; + + /* Switch info specific */ + dev_info->switch_info.name = ethdev->device->name; + dev_info->switch_info.domain_id = rep_dev->switch_domain_id; + dev_info->switch_info.port_id = rep_dev->vf_id; + return 0; +fail: + return rc; +} + +static inline int +bitmap_ctzll(uint64_t slab) +{ + if (slab == 0) + return 0; + + return __builtin_ctzll(slab); +} + +static uint16_t +alloc_rep_xport_qid(struct plt_bitmap *bmp) +{ + uint16_t idx, rc; + uint64_t slab; + uint32_t pos; + + pos = 0; + slab = 0; + /* Scan from the beginning */ + plt_bitmap_scan_init(bmp); + /* Scan bitmap to get the free pool */ + rc = plt_bitmap_scan(bmp, &pos, &slab); + /* Empty bitmap */ + if (rc == 0) + return UINT16_MAX; + + idx = pos + bitmap_ctzll(slab); + plt_bitmap_clear(bmp, idx); + return idx; +} + +static int +configure_rep_xport_queues_map(rep_xport_vdev_cfg_t *rep_xport_vdev_cfg) +{ + int id, rc = 0, q_max; + uint32_t bmap_sz; + void *bmap_mem; + + q_max = CNXK_MAX_REP_PORTS + 1; + /* Return success on no-pci case */ + if (!q_max) + return 0; + + bmap_sz = plt_bitmap_get_memory_footprint(q_max); + + /* Allocate memory for rep_xport queue bitmap */ + bmap_mem = plt_zmalloc(bmap_sz, RTE_CACHE_LINE_SIZE); + if (bmap_mem == NULL) { + plt_err("Failed to allocate memory for worker lmt bmap"); + rc = -ENOMEM; + goto exit; + } + rep_xport_vdev_cfg->q_bmap_mem = bmap_mem; + + /* Initialize worker lmt bitmap */ + rep_xport_vdev_cfg->q_map = plt_bitmap_init(q_max, bmap_mem, bmap_sz); + if (!rep_xport_vdev_cfg->q_map) { + plt_err("Failed to initialize rep_xport queue bitmap"); + rc = -EIO; + goto exit; + } + + /* Set all the queue initially */ + for (id = 0; id < q_max; id++) + plt_bitmap_set(rep_xport_vdev_cfg->q_bmap_mem, id); + + return 0; +exit: + return rc; +} + +static uint16_t +cnxk_rep_eth_dev_count_total(void) +{ + uint16_t port, count = 0; + struct rte_eth_dev *ethdev; + + RTE_ETH_FOREACH_DEV(port) { + ethdev = &rte_eth_devices[port]; + if (ethdev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) + count++; + } + + return count; +} + +static int +configure_control_channel(rep_xport_vdev_cfg_t *rep_xport_vdev_cfg, uint16_t portid) +{ + struct rte_mempool *ctrl_chan_pool = NULL; + int rc; + + /* Allocate a qid for control channel */ + alloc_rep_xport_qid(rep_xport_vdev_cfg->q_map); + + /* Create the mbuf pool. */ + ctrl_chan_pool = rte_pktmbuf_pool_create("rep_xport_ctrl_pool", NB_REP_VDEV_MBUF, + MEMPOOL_CACHE_SIZE, RTE_CACHE_LINE_SIZE, + RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); + + if (ctrl_chan_pool == NULL) { + plt_err("Cannot init mbuf pool"); + rc = -ENOMEM; + goto fail; + } + + /* Setup a RX queue for control channel */ + rc = rte_eth_rx_queue_setup(portid, CNXK_REP_VDEV_CTRL_QUEUE, RX_DESC_PER_QUEUE, + rte_eth_dev_socket_id(portid), NULL, ctrl_chan_pool); + if (rc < 0) { + plt_err("rte_eth_rx_queue_setup:err=%d, port=%u\n", rc, portid); + goto fail; + } + + /* Setup a TX queue for control channel */ + rc = rte_eth_tx_queue_setup(portid, CNXK_REP_VDEV_CTRL_QUEUE, TX_DESC_PER_QUEUE, + rte_eth_dev_socket_id(portid), NULL); + if (rc < 0) { + plt_err("TX queue setup failed, err %d port %d", rc, portid); + goto fail; + } + + rep_xport_vdev_cfg->ctrl_chan_pool = ctrl_chan_pool; + + return 0; +fail: + return rc; +} + +static int +configure_rep_xport_dev(rep_xport_vdev_cfg_t *rep_xport_vdev_cfg, uint16_t portid) +{ + struct rte_eth_dev *rep_xport_ethdev = cnxk_rep_xport_eth_dev(portid); + static struct rte_eth_conf port_conf_default; + uint16_t nb_rxq, nb_txq, nb_rep_ports; + int rc = 0; + + /* If rep_xport port already started, stop it and reconfigure */ + if (rep_xport_ethdev->data->dev_started) + rte_eth_dev_stop(portid); + + /* Get the no of representors probed */ + nb_rep_ports = cnxk_rep_eth_dev_count_total(); + if (nb_rep_ports > CNXK_MAX_REP_PORTS) { + plt_err("Representors probed %d > Max supported %d", nb_rep_ports, + CNXK_MAX_REP_PORTS); + goto fail; + } + + /* Each queue of rep_xport describes representor port. 1 additional queue is + * configured as control channel to configure flows, etc. + */ + nb_rxq = CNXK_MAX_REP_PORTS + 1; + nb_txq = CNXK_MAX_REP_PORTS + 1; + + rc = rte_eth_dev_configure(portid, nb_rxq, nb_txq, &port_conf_default); + if (rc) { + plt_err("Failed to configure rep_xport port: %d", rc); + goto fail; + } + + rep_xport_vdev_cfg->rep_xport_configured = true; + rep_xport_vdev_cfg->nb_rep_ports = nb_rep_ports; + + return 0; +fail: + return rc; } int cnxk_rep_dev_configure(struct rte_eth_dev *ethdev) { - PLT_SET_USED(ethdev); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + int rc = -1; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + mz = plt_memzone_reserve_cache_align(CNXK_REP_XPORT_VDEV_CFG_MZ, + sizeof(rep_xport_vdev_cfg_t)); + if (!mz) { + plt_err("Failed to reserve a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + } + + rep_xport_vdev_cfg = mz->addr; + /* Return if rep_xport dev already configured */ + if (rep_xport_vdev_cfg->rep_xport_configured) { + rep_dev->ctrl_chan_pool = rep_xport_vdev_cfg->ctrl_chan_pool; + return 0; + } + + /* Configure rep_xport pmd */ + rc = configure_rep_xport_dev(rep_xport_vdev_cfg, rep_dev->rep_xport_vdev); + if (rc) { + plt_err("Configuring rep_xport port failed"); + goto free; + } + + /* Setup a bitmap for rep_xport queues */ + rc = configure_rep_xport_queues_map(rep_xport_vdev_cfg); + if (rc != 0) { + plt_err("Failed to setup rep_xport queue map, err %d", rc); + goto free; + } + + /* Setup a queue for control channel */ + rc = configure_control_channel(rep_xport_vdev_cfg, rep_dev->rep_xport_vdev); + if (rc != 0) { + plt_err("Failed to setup control channgel, err %d", rc); + goto free; + } + rep_dev->ctrl_chan_pool = rep_xport_vdev_cfg->ctrl_chan_pool; + return 0; +free: + plt_memzone_free(mz); +fail: + return rc; } int -cnxk_rep_dev_start(struct rte_eth_dev *ethdev) +cnxk_rep_promiscuous_enable(struct rte_eth_dev *ethdev) { PLT_SET_USED(ethdev); return 0; } int -cnxk_rep_dev_close(struct rte_eth_dev *ethdev) +cnxk_rep_promiscuous_disable(struct rte_eth_dev *ethdev) { PLT_SET_USED(ethdev); return 0; } +int +cnxk_rep_dev_start(struct rte_eth_dev *ethdev) +{ + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + int rc = 0; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + + rep_xport_vdev_cfg = mz->addr; + ethdev->rx_pkt_burst = cnxk_rep_rx_burst; + ethdev->tx_pkt_burst = cnxk_rep_tx_burst; + + /* Start rep_xport device only once after first representor gets active */ + if (!rep_xport_vdev_cfg->nb_rep_started) { + rc = rte_eth_dev_start(rep_dev->rep_xport_vdev); + if (rc) { + plt_err("Rep base vdev portid %d start failed, err %d", + rep_dev->rep_xport_vdev, rc); + goto fail; + } + + /* Launch a thread to handle control messages */ + rc = cnxk_rep_control_thread_launch(cnxk_eth_pmd_priv(rep_dev->parent_dev)); + if (rc) { + plt_err("Failed to launch message ctrl thread"); + goto fail; + } + } + + rep_xport_vdev_cfg->nb_rep_started++; + + return 0; +fail: + return rc; +} + +int +cnxk_rep_dev_close(struct rte_eth_dev *ethdev) +{ + return cnxk_rep_dev_uninit(ethdev); +} + int cnxk_rep_dev_stop(struct rte_eth_dev *ethdev) { - PLT_SET_USED(ethdev); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + + rep_xport_vdev_cfg = mz->addr; + ethdev->rx_pkt_burst = cnxk_rep_rx_burst_dummy; + ethdev->tx_pkt_burst = cnxk_rep_tx_burst_dummy; + rep_xport_vdev_cfg->nb_rep_started--; + + /* Stop rep_xport device only after all other devices stopped */ + if (!rep_xport_vdev_cfg->nb_rep_started) + rte_eth_dev_stop(rep_dev->rep_xport_vdev); + return 0; +fail: + return rte_errno; } int @@ -53,54 +441,220 @@ cnxk_rep_rx_queue_setup(struct rte_eth_dev *ethdev, uint16_t rx_queue_id, uint16 unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool) { - PLT_SET_USED(ethdev); - PLT_SET_USED(rx_queue_id); - PLT_SET_USED(nb_rx_desc); - PLT_SET_USED(socket_id); - PLT_SET_USED(rx_conf); - PLT_SET_USED(mb_pool); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + int rc = 0; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + + rep_xport_vdev_cfg = mz->addr; + /* Allocate a qid, if tx queue setup already done use the same qid */ + if (rep_dev->u.rxq == UINT16_MAX && rep_dev->u.txq == UINT16_MAX) + rep_dev->u.rxq = alloc_rep_xport_qid(rep_xport_vdev_cfg->q_map); + else + rep_dev->u.rxq = rep_dev->u.txq; + + /* Setup the RX queue */ + rc = rte_eth_rx_queue_setup(rep_dev->rep_xport_vdev, rep_dev->u.rxq, nb_rx_desc, socket_id, + rx_conf, mb_pool); + if (rc < 0) { + plt_err("rte_eth_rx_queue_setup:err=%d, port=%u\n", rc, rep_dev->rep_xport_vdev); + goto fail; + } + + ethdev->data->rx_queues[rx_queue_id] = rep_dev; + plt_info("Representor id %d portid %d rxq %d", rep_dev->vf_id, ethdev->data->port_id, + rep_dev->u.rxq); + return 0; +fail: + return rc; } void cnxk_rep_rx_queue_release(struct rte_eth_dev *ethdev, uint16_t queue_id) { - PLT_SET_USED(ethdev); - PLT_SET_USED(queue_id); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + RTE_SET_USED(queue_id); + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + return; + } + + rep_xport_vdev_cfg = mz->addr; + plt_bitmap_clear(rep_xport_vdev_cfg->q_bmap_mem, rep_dev->u.rxq); } int cnxk_rep_tx_queue_setup(struct rte_eth_dev *ethdev, uint16_t tx_queue_id, uint16_t nb_tx_desc, unsigned int socket_id, const struct rte_eth_txconf *tx_conf) { - PLT_SET_USED(ethdev); - PLT_SET_USED(tx_queue_id); - PLT_SET_USED(nb_tx_desc); - PLT_SET_USED(socket_id); - PLT_SET_USED(tx_conf); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; + int rc = 0; + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + goto fail; + } + + rep_xport_vdev_cfg = mz->addr; + /* Allocate a qid, if rx queue setup already done use the same qid */ + if (rep_dev->u.rxq == UINT16_MAX && rep_dev->u.txq == UINT16_MAX) + rep_dev->u.txq = alloc_rep_xport_qid(rep_xport_vdev_cfg->q_map); + else + rep_dev->u.txq = rep_dev->u.rxq; + + /* Setup the TX queue */ + rc = rte_eth_tx_queue_setup(rep_dev->rep_xport_vdev, rep_dev->u.txq, nb_tx_desc, socket_id, + tx_conf); + if (rc < 0) { + plt_err("TX queue setup failed, err %d port %d", rc, rep_dev->rep_xport_vdev); + goto fail; + } + + ethdev->data->tx_queues[tx_queue_id] = rep_dev; + plt_info("Representor id %d portid %d txq %d", rep_dev->vf_id, ethdev->data->port_id, + rep_dev->u.txq); + return 0; +fail: + return rc; } void cnxk_rep_tx_queue_release(struct rte_eth_dev *ethdev, uint16_t queue_id) { - PLT_SET_USED(ethdev); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + rep_xport_vdev_cfg_t *rep_xport_vdev_cfg = NULL; + const struct plt_memzone *mz; PLT_SET_USED(queue_id); + + mz = plt_memzone_lookup(CNXK_REP_XPORT_VDEV_CFG_MZ); + if (!mz) { + plt_err("Failed to lookup a memzone, rep id %d, err %d", + rep_dev->vf_id, rte_errno); + return; + } + + rep_xport_vdev_cfg = mz->addr; + plt_bitmap_clear(rep_xport_vdev_cfg->q_bmap_mem, rep_dev->u.txq); +} + +static int +process_eth_stats(struct cnxk_rep_dev *rep_dev, cnxk_rep_msg_ack_data_t *adata, cnxk_rep_msg_t msg) +{ + cnxk_rep_msg_eth_stats_meta_t msg_st_meta; + uint32_t len = 0, rc; + void *buffer; + size_t size; + + size = CNXK_REP_MSG_MAX_BUFFER_SZ; + buffer = plt_zmalloc(size, 0); + if (!buffer) { + plt_err("Failed to allocate mem"); + rc = -ENOMEM; + goto fail; + } + + cnxk_rep_msg_populate_header(buffer, &len); + + msg_st_meta.portid = rep_dev->u.rxq; + cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_st_meta, + sizeof(cnxk_rep_msg_eth_stats_meta_t), msg); + cnxk_rep_msg_populate_msg_end(buffer, &len); + + rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, adata); + if (rc) { + plt_err("Failed to process the message, err %d", rc); + goto fail; + } + + rte_free(buffer); + + return 0; +fail: + rte_free(buffer); + return rc; } int cnxk_rep_stats_get(struct rte_eth_dev *ethdev, struct rte_eth_stats *stats) { - PLT_SET_USED(ethdev); - PLT_SET_USED(stats); + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + struct rte_eth_stats vf_stats; + cnxk_rep_msg_ack_data_t adata; + int rc; + + /* If representor not representing any active VF, return 0 */ + if (!rep_dev->is_vf_active) + return 0; + + rc = process_eth_stats(rep_dev, &adata, CNXK_REP_MSG_ETH_STATS_GET); + if (rc || adata.u.sval < 0) { + if (adata.u.sval < 0) + rc = adata.u.sval; + + plt_err("Failed to clear stats for vf rep %x, err %d", rep_dev->vf_id, rc); + } + + if (adata.size != sizeof(struct rte_eth_stats)) { + rc = -EINVAL; + plt_err("Incomplete stats received for vf rep %d", rep_dev->vf_id); + goto fail; + } + + rte_memcpy(&vf_stats, adata.u.data, adata.size); + + stats->q_ipackets[0] = vf_stats.ipackets; + stats->q_ibytes[0] = vf_stats.ibytes; + stats->ipackets = vf_stats.ipackets; + stats->ibytes = vf_stats.ibytes; + + stats->q_opackets[0] = vf_stats.opackets; + stats->q_obytes[0] = vf_stats.obytes; + stats->opackets = vf_stats.opackets; + stats->obytes = vf_stats.obytes; + return 0; +fail: + return rc; } int cnxk_rep_stats_reset(struct rte_eth_dev *ethdev) { - PLT_SET_USED(ethdev); - return 0; + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(ethdev); + cnxk_rep_msg_ack_data_t adata; + int rc = 0; + + /* If representor not representing any active VF, return 0 */ + if (!rep_dev->is_vf_active) + return 0; + + rc = process_eth_stats(rep_dev, &adata, CNXK_REP_MSG_ETH_STATS_CLEAR); + if (rc || adata.u.sval < 0) { + if (adata.u.sval < 0) + rc = adata.u.sval; + + plt_err("Failed to clear stats for vf rep %x, err %d", rep_dev->vf_id, rc); + } + + return rc; } int @@ -110,3 +664,54 @@ cnxk_rep_flow_ops_get(struct rte_eth_dev *ethdev, const struct rte_flow_ops **op PLT_SET_USED(ops); return 0; } + +int +cnxk_rep_mac_addr_set(struct rte_eth_dev *eth_dev, struct rte_ether_addr *addr) +{ + struct cnxk_rep_dev *rep_dev = cnxk_rep_pmd_priv(eth_dev); + cnxk_rep_msg_eth_set_mac_meta_t msg_sm_meta; + cnxk_rep_msg_ack_data_t adata; + uint32_t len = 0, rc; + void *buffer; + size_t size; + + /* If representor not representing any VF, return 0 */ + if (!rep_dev->is_vf_active) + return 0; + + size = CNXK_REP_MSG_MAX_BUFFER_SZ; + buffer = plt_zmalloc(size, 0); + if (!buffer) { + plt_err("Failed to allocate mem"); + rc = -ENOMEM; + goto fail; + } + + cnxk_rep_msg_populate_header(buffer, &len); + + msg_sm_meta.portid = rep_dev->u.rxq; + rte_memcpy(&msg_sm_meta.addr_bytes, addr->addr_bytes, RTE_ETHER_ADDR_LEN); + cnxk_rep_msg_populate_command_meta(buffer, &len, &msg_sm_meta, + sizeof(cnxk_rep_msg_eth_set_mac_meta_t), + CNXK_REP_MSG_ETH_SET_MAC); + cnxk_rep_msg_populate_msg_end(buffer, &len); + + rc = cnxk_rep_msg_send_process(rep_dev, buffer, len, &adata); + if (rc) { + plt_err("Failed to process the message, err %d", rc); + goto fail; + } + + if (adata.u.sval < 0) { + rc = adata.u.sval; + plt_err("Failed to set mac address, err %d", rc); + goto fail; + } + + rte_free(buffer); + + return 0; +fail: + rte_free(buffer); + return rc; +} -- 2.18.0