From patchwork Thu Jun 17 10:59:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiawen Wu X-Patchwork-Id: 94338 X-Patchwork-Delegate: andrew.rybchenko@oktetlabs.ru Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id CD021A0C4D; Thu, 17 Jun 2021 12:59:47 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 788AD41163; Thu, 17 Jun 2021 12:58:36 +0200 (CEST) Received: from smtpbgau1.qq.com (smtpbgau1.qq.com [54.206.16.166]) by mails.dpdk.org (Postfix) with ESMTP id B4C1F41120 for ; Thu, 17 Jun 2021 12:58:34 +0200 (CEST) X-QQ-mid: bizesmtp46t1623927508ta0qakwu Received: from wxdbg.localdomain.com (unknown [183.129.236.74]) by esmtp6.qq.com (ESMTP) with id ; Thu, 17 Jun 2021 18:58:28 +0800 (CST) X-QQ-SSF: 01400000000000D0E000B00A0000000 X-QQ-FEAT: pLTyZv4M7ZIJVBS7X/nIn+MpxBMKJv5z1lIrp3vKo9+Es3uN1v8/NOZDfX4+C elpsaXkm7bbiI1zHdxJqsrc4qFjHKHKxTCm3EtWQ/MDNdRqBTJJ90ao+bvzkTGaXiUuHI3n FwV7UkMkAmEvGl+0n9nv7u73XuUCVLMPeLYWVvCBiFUWD+IKmT+/NWFB/GSmCpXIieW/5oG II4uL4keqjSM1RfgEfbX/oe3h/A0PFhbdjfzY+aFiUHyAYWt0U2AZ4r/uZhxpennGJRf/pl RZJGQWpy0nNEo13j1UMeGElrjT50b/YnRw3Tp6QeL9vMHm/IHcwBqTPGbepdZQ4Bpu5ygUK pzej9zOci98NLoEDxmL6mITChKF4G7y0TWDxMN1 X-QQ-GoodBg: 2 From: Jiawen Wu To: dev@dpdk.org Cc: Jiawen Wu Date: Thu, 17 Jun 2021 18:59:59 +0800 Message-Id: <20210617110005.4132926-14-jiawenwu@trustnetic.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210617110005.4132926-1-jiawenwu@trustnetic.com> References: <20210617110005.4132926-1-jiawenwu@trustnetic.com> MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:trustnetic.com:qybgforeign:qybgforeign5 X-QQ-Bgrelay: 1 Subject: [dpdk-dev] [PATCH v6 13/19] net/ngbe: add Tx queue setup and release 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 Sender: "dev" Setup device Tx queue and release Tx queue. Signed-off-by: Jiawen Wu --- drivers/net/ngbe/ngbe_ethdev.c | 24 ++++ drivers/net/ngbe/ngbe_ethdev.h | 11 ++ drivers/net/ngbe/ngbe_rxtx.c | 206 +++++++++++++++++++++++++++++++++ drivers/net/ngbe/ngbe_rxtx.h | 95 +++++++++++++++ 4 files changed, 336 insertions(+) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index e73606c5f3..d6f93cfe46 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -44,6 +44,14 @@ static const struct rte_eth_desc_lim rx_desc_lim = { .nb_align = NGBE_RXD_ALIGN, }; +static const struct rte_eth_desc_lim tx_desc_lim = { + .nb_max = NGBE_RING_DESC_MAX, + .nb_min = NGBE_RING_DESC_MIN, + .nb_align = NGBE_TXD_ALIGN, + .nb_seg_max = NGBE_TX_MAX_SEG, + .nb_mtu_seg_max = NGBE_TX_MAX_SEG, +}; + static const struct eth_dev_ops ngbe_eth_dev_ops; static inline void @@ -283,6 +291,7 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) struct ngbe_hw *hw = ngbe_dev_hw(dev); dev_info->max_rx_queues = (uint16_t)hw->mac.max_rx_queues; + dev_info->max_tx_queues = (uint16_t)hw->mac.max_tx_queues; dev_info->default_rxconf = (struct rte_eth_rxconf) { .rx_thresh = { @@ -295,14 +304,27 @@ ngbe_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) .offloads = 0, }; + dev_info->default_txconf = (struct rte_eth_txconf) { + .tx_thresh = { + .pthresh = NGBE_DEFAULT_TX_PTHRESH, + .hthresh = NGBE_DEFAULT_TX_HTHRESH, + .wthresh = NGBE_DEFAULT_TX_WTHRESH, + }, + .tx_free_thresh = NGBE_DEFAULT_TX_FREE_THRESH, + .offloads = 0, + }; + dev_info->rx_desc_lim = rx_desc_lim; + dev_info->tx_desc_lim = tx_desc_lim; dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_100M | ETH_LINK_SPEED_10M; /* Driver-preferred Rx/Tx parameters */ dev_info->default_rxportconf.nb_queues = 1; + dev_info->default_txportconf.nb_queues = 1; dev_info->default_rxportconf.ring_size = 256; + dev_info->default_txportconf.ring_size = 256; return 0; } @@ -605,6 +627,8 @@ static const struct eth_dev_ops ngbe_eth_dev_ops = { .link_update = ngbe_dev_link_update, .rx_queue_setup = ngbe_dev_rx_queue_setup, .rx_queue_release = ngbe_dev_rx_queue_release, + .tx_queue_setup = ngbe_dev_tx_queue_setup, + .tx_queue_release = ngbe_dev_tx_queue_release, }; RTE_PMD_REGISTER_PCI(net_ngbe, rte_ngbe_pmd); diff --git a/drivers/net/ngbe/ngbe_ethdev.h b/drivers/net/ngbe/ngbe_ethdev.h index 6580d288c8..131671c313 100644 --- a/drivers/net/ngbe/ngbe_ethdev.h +++ b/drivers/net/ngbe/ngbe_ethdev.h @@ -61,11 +61,17 @@ ngbe_dev_intr(struct rte_eth_dev *dev) void ngbe_dev_rx_queue_release(void *rxq); +void ngbe_dev_tx_queue_release(void *txq); + int ngbe_dev_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id, uint16_t nb_rx_desc, unsigned int socket_id, const struct rte_eth_rxconf *rx_conf, struct rte_mempool *mb_pool); +int ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id, + uint16_t nb_tx_desc, unsigned int socket_id, + const struct rte_eth_txconf *tx_conf); + int ngbe_dev_link_update_share(struct rte_eth_dev *dev, int wait_to_complete); @@ -82,4 +88,9 @@ ngbe_dev_link_update_share(struct rte_eth_dev *dev, #define NGBE_DEFAULT_RX_HTHRESH 8 #define NGBE_DEFAULT_RX_WTHRESH 0 +#define NGBE_DEFAULT_TX_FREE_THRESH 32 +#define NGBE_DEFAULT_TX_PTHRESH 32 +#define NGBE_DEFAULT_TX_HTHRESH 0 +#define NGBE_DEFAULT_TX_WTHRESH 0 + #endif /* _NGBE_ETHDEV_H_ */ diff --git a/drivers/net/ngbe/ngbe_rxtx.c b/drivers/net/ngbe/ngbe_rxtx.c index df0b64dc01..da9150b2f1 100644 --- a/drivers/net/ngbe/ngbe_rxtx.c +++ b/drivers/net/ngbe/ngbe_rxtx.c @@ -15,6 +15,212 @@ #include "ngbe_ethdev.h" #include "ngbe_rxtx.h" +/********************************************************************* + * + * Queue management functions + * + **********************************************************************/ + +static void __rte_cold +ngbe_tx_queue_release_mbufs(struct ngbe_tx_queue *txq) +{ + unsigned int i; + + if (txq->sw_ring != NULL) { + for (i = 0; i < txq->nb_tx_desc; i++) { + if (txq->sw_ring[i].mbuf != NULL) { + rte_pktmbuf_free_seg(txq->sw_ring[i].mbuf); + txq->sw_ring[i].mbuf = NULL; + } + } + } +} + +static void __rte_cold +ngbe_tx_free_swring(struct ngbe_tx_queue *txq) +{ + if (txq != NULL) + rte_free(txq->sw_ring); +} + +static void __rte_cold +ngbe_tx_queue_release(struct ngbe_tx_queue *txq) +{ + if (txq != NULL) { + if (txq->ops != NULL) { + txq->ops->release_mbufs(txq); + txq->ops->free_swring(txq); + } + rte_free(txq); + } +} + +void __rte_cold +ngbe_dev_tx_queue_release(void *txq) +{ + ngbe_tx_queue_release(txq); +} + +/* (Re)set dynamic ngbe_tx_queue fields to defaults */ +static void __rte_cold +ngbe_reset_tx_queue(struct ngbe_tx_queue *txq) +{ + static const struct ngbe_tx_desc zeroed_desc = {0}; + struct ngbe_tx_entry *txe = txq->sw_ring; + uint16_t prev, i; + + /* Zero out HW ring memory */ + for (i = 0; i < txq->nb_tx_desc; i++) + txq->tx_ring[i] = zeroed_desc; + + /* Initialize SW ring entries */ + prev = (uint16_t)(txq->nb_tx_desc - 1); + for (i = 0; i < txq->nb_tx_desc; i++) { + /* the ring can also be modified by hardware */ + volatile struct ngbe_tx_desc *txd = &txq->tx_ring[i]; + + txd->dw3 = rte_cpu_to_le_32(NGBE_TXD_DD); + txe[i].mbuf = NULL; + txe[i].last_id = i; + txe[prev].next_id = i; + prev = i; + } + + txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); + txq->tx_tail = 0; + + /* + * Always allow 1 descriptor to be un-allocated to avoid + * a H/W race condition + */ + txq->last_desc_cleaned = (uint16_t)(txq->nb_tx_desc - 1); + txq->nb_tx_free = (uint16_t)(txq->nb_tx_desc - 1); + txq->ctx_curr = 0; + memset((void *)&txq->ctx_cache, 0, + NGBE_CTX_NUM * sizeof(struct ngbe_ctx_info)); +} + +static const struct ngbe_txq_ops def_txq_ops = { + .release_mbufs = ngbe_tx_queue_release_mbufs, + .free_swring = ngbe_tx_free_swring, + .reset = ngbe_reset_tx_queue, +}; + +int __rte_cold +ngbe_dev_tx_queue_setup(struct rte_eth_dev *dev, + uint16_t queue_idx, + uint16_t nb_desc, + unsigned int socket_id, + const struct rte_eth_txconf *tx_conf) +{ + const struct rte_memzone *tz; + struct ngbe_tx_queue *txq; + struct ngbe_hw *hw; + uint16_t tx_free_thresh; + + PMD_INIT_FUNC_TRACE(); + hw = ngbe_dev_hw(dev); + + /* + * Validate number of transmit descriptors. + * It must not exceed hardware maximum, and must be multiple + * of NGBE_ALIGN. + */ + if (nb_desc % NGBE_TXD_ALIGN != 0 || + nb_desc > NGBE_RING_DESC_MAX || + nb_desc < NGBE_RING_DESC_MIN) { + return -EINVAL; + } + + /* + * The Tx descriptor ring will be cleaned after txq->tx_free_thresh + * descriptors are used or if the number of descriptors required + * to transmit a packet is greater than the number of free Tx + * descriptors. + * One descriptor in the Tx ring is used as a sentinel to avoid a + * H/W race condition, hence the maximum threshold constraints. + * When set to zero use default values. + */ + tx_free_thresh = (uint16_t)((tx_conf->tx_free_thresh) ? + tx_conf->tx_free_thresh : DEFAULT_TX_FREE_THRESH); + if (tx_free_thresh >= (nb_desc - 3)) { + PMD_INIT_LOG(ERR, "tx_free_thresh must be less than the number of " + "TX descriptors minus 3. (tx_free_thresh=%u " + "port=%d queue=%d)", + (unsigned int)tx_free_thresh, + (int)dev->data->port_id, (int)queue_idx); + return -(EINVAL); + } + + if (nb_desc % tx_free_thresh != 0) { + PMD_INIT_LOG(ERR, "tx_free_thresh must be a divisor of the " + "number of Tx descriptors. (tx_free_thresh=%u " + "port=%d queue=%d)", (unsigned int)tx_free_thresh, + (int)dev->data->port_id, (int)queue_idx); + return -(EINVAL); + } + + /* Free memory prior to re-allocation if needed... */ + if (dev->data->tx_queues[queue_idx] != NULL) { + ngbe_tx_queue_release(dev->data->tx_queues[queue_idx]); + dev->data->tx_queues[queue_idx] = NULL; + } + + /* First allocate the Tx queue data structure */ + txq = rte_zmalloc_socket("ethdev Tx queue", + sizeof(struct ngbe_tx_queue), + RTE_CACHE_LINE_SIZE, socket_id); + if (txq == NULL) + return -ENOMEM; + + /* + * Allocate Tx ring hardware descriptors. A memzone large enough to + * handle the maximum ring size is allocated in order to allow for + * resizing in later calls to the queue setup function. + */ + tz = rte_eth_dma_zone_reserve(dev, "tx_ring", queue_idx, + sizeof(struct ngbe_tx_desc) * NGBE_RING_DESC_MAX, + NGBE_ALIGN, socket_id); + if (tz == NULL) { + ngbe_tx_queue_release(txq); + return -ENOMEM; + } + + txq->nb_tx_desc = nb_desc; + txq->tx_free_thresh = tx_free_thresh; + txq->pthresh = tx_conf->tx_thresh.pthresh; + txq->hthresh = tx_conf->tx_thresh.hthresh; + txq->wthresh = tx_conf->tx_thresh.wthresh; + txq->queue_id = queue_idx; + txq->reg_idx = queue_idx; + txq->port_id = dev->data->port_id; + txq->ops = &def_txq_ops; + txq->tx_deferred_start = tx_conf->tx_deferred_start; + + txq->tdt_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXWP(txq->reg_idx)); + txq->tdc_reg_addr = NGBE_REG_ADDR(hw, NGBE_TXCFG(txq->reg_idx)); + + txq->tx_ring_phys_addr = TMZ_PADDR(tz); + txq->tx_ring = (struct ngbe_tx_desc *)TMZ_VADDR(tz); + + /* Allocate software ring */ + txq->sw_ring = rte_zmalloc_socket("txq->sw_ring", + sizeof(struct ngbe_tx_entry) * nb_desc, + RTE_CACHE_LINE_SIZE, socket_id); + if (txq->sw_ring == NULL) { + ngbe_tx_queue_release(txq); + return -ENOMEM; + } + PMD_INIT_LOG(DEBUG, "sw_ring=%p hw_ring=%p dma_addr=0x%" PRIx64, + txq->sw_ring, txq->tx_ring, txq->tx_ring_phys_addr); + + txq->ops->reset(txq); + + dev->data->tx_queues[queue_idx] = txq; + + return 0; +} + /** * ngbe_free_sc_cluster - free the not-yet-completed scattered cluster * diff --git a/drivers/net/ngbe/ngbe_rxtx.h b/drivers/net/ngbe/ngbe_rxtx.h index 92b9a9fd1b..0f2c185dbf 100644 --- a/drivers/net/ngbe/ngbe_rxtx.h +++ b/drivers/net/ngbe/ngbe_rxtx.h @@ -43,11 +43,41 @@ struct ngbe_rx_desc { } qw1; /* also as r.hdr_addr */ }; +/***************************************************************************** + * Transmit Descriptor + *****************************************************************************/ +/** + * Transmit Context Descriptor (NGBE_TXD_TYP=CTXT) + **/ +struct ngbe_tx_ctx_desc { + rte_le32_t dw0; /* w.vlan_macip_lens */ + rte_le32_t dw1; /* w.seqnum_seed */ + rte_le32_t dw2; /* w.type_tucmd_mlhl */ + rte_le32_t dw3; /* w.mss_l4len_idx */ +}; + +/* @ngbe_tx_ctx_desc.dw3 */ +#define NGBE_TXD_DD MS(0, 0x1) /* descriptor done */ + +/** + * Transmit Data Descriptor (NGBE_TXD_TYP=DATA) + **/ +struct ngbe_tx_desc { + rte_le64_t qw0; /* r.buffer_addr , w.reserved */ + rte_le32_t dw2; /* r.cmd_type_len, w.nxtseq_seed */ + rte_le32_t dw3; /* r.olinfo_status, w.status */ +}; + #define RTE_PMD_NGBE_RX_MAX_BURST 32 #define RX_RING_SZ ((NGBE_RING_DESC_MAX + RTE_PMD_NGBE_RX_MAX_BURST) * \ sizeof(struct ngbe_rx_desc)) +#define NGBE_TX_MAX_SEG 40 + +#ifndef DEFAULT_TX_FREE_THRESH +#define DEFAULT_TX_FREE_THRESH 32 +#endif /** * Structure associated with each descriptor of the Rx ring of a Rx queue. @@ -60,6 +90,15 @@ struct ngbe_scattered_rx_entry { struct rte_mbuf *fbuf; /**< First segment of the fragmented packet. */ }; +/** + * Structure associated with each descriptor of the Tx ring of a Tx queue. + */ +struct ngbe_tx_entry { + struct rte_mbuf *mbuf; /**< mbuf associated with Tx desc, if any. */ + uint16_t next_id; /**< Index of next descriptor in ring. */ + uint16_t last_id; /**< Index of last scattered descriptor. */ +}; + /** * Structure associated with each Rx queue. */ @@ -93,4 +132,60 @@ struct ngbe_rx_queue { struct rte_mbuf *rx_stage[RTE_PMD_NGBE_RX_MAX_BURST * 2]; }; +/** + * NGBE CTX Constants + */ +enum ngbe_ctx_num { + NGBE_CTX_0 = 0, /**< CTX0 */ + NGBE_CTX_1 = 1, /**< CTX1 */ + NGBE_CTX_NUM = 2, /**< CTX NUMBER */ +}; + +/** + * Structure to check if new context need be built + */ +struct ngbe_ctx_info { + uint64_t flags; /**< ol_flags for context build. */ +}; + +/** + * Structure associated with each Tx queue. + */ +struct ngbe_tx_queue { + /** Tx ring virtual address. */ + volatile struct ngbe_tx_desc *tx_ring; + uint64_t tx_ring_phys_addr; /**< Tx ring DMA address. */ + struct ngbe_tx_entry *sw_ring; /**< address of SW ring for scalar PMD.*/ + volatile uint32_t *tdt_reg_addr; /**< Address of TDT register. */ + volatile uint32_t *tdc_reg_addr; /**< Address of TDC register. */ + uint16_t nb_tx_desc; /**< number of Tx descriptors. */ + uint16_t tx_tail; /**< current value of TDT reg. */ + /**< Start freeing Tx buffers if there are less free descriptors than + * this value. + */ + uint16_t tx_free_thresh; + /** Index to last Tx descriptor to have been cleaned. */ + uint16_t last_desc_cleaned; + /** Total number of Tx descriptors ready to be allocated. */ + uint16_t nb_tx_free; + uint16_t tx_next_dd; /**< next desc to scan for DD bit */ + uint16_t queue_id; /**< Tx queue index. */ + uint16_t reg_idx; /**< Tx queue register index. */ + uint16_t port_id; /**< Device port identifier. */ + uint8_t pthresh; /**< Prefetch threshold register. */ + uint8_t hthresh; /**< Host threshold register. */ + uint8_t wthresh; /**< Write-back threshold reg. */ + uint32_t ctx_curr; /**< Hardware context states. */ + /** Hardware context0 history. */ + struct ngbe_ctx_info ctx_cache[NGBE_CTX_NUM]; + const struct ngbe_txq_ops *ops; /**< txq ops */ + uint8_t tx_deferred_start; /**< not in global dev start. */ +}; + +struct ngbe_txq_ops { + void (*release_mbufs)(struct ngbe_tx_queue *txq); + void (*free_swring)(struct ngbe_tx_queue *txq); + void (*reset)(struct ngbe_tx_queue *txq); +}; + #endif /* _NGBE_RXTX_H_ */