net/ngbe: support Tx queue setup/release
Setup device Tx queue and release Tx queue. Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
This commit is contained in:
parent
43b7e5ea60
commit
a58e7c312c
drivers/net/ngbe
@ -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;
|
||||
}
|
||||
@ -594,6 +616,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);
|
||||
|
@ -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_ */
|
||||
|
@ -15,6 +15,201 @@
|
||||
#include "ngbe_ethdev.h"
|
||||
#include "ngbe_rxtx.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Queue management functions
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
static void
|
||||
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
|
||||
ngbe_tx_free_swring(struct ngbe_tx_queue *txq)
|
||||
{
|
||||
if (txq != NULL)
|
||||
rte_free(txq->sw_ring);
|
||||
}
|
||||
|
||||
static void
|
||||
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
|
||||
ngbe_dev_tx_queue_release(void *txq)
|
||||
{
|
||||
ngbe_tx_queue_release(txq);
|
||||
}
|
||||
|
||||
/* (Re)set dynamic ngbe_tx_queue fields to defaults */
|
||||
static void
|
||||
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
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
|
@ -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.
|
||||
*/
|
||||
@ -97,4 +136,63 @@ 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];
|
||||
uint8_t tx_deferred_start; /**< not in global dev start */
|
||||
|
||||
const struct ngbe_txq_ops *ops; /**< txq ops */
|
||||
};
|
||||
|
||||
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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user