net/bnxt: support Rx/Tx queue start/stop
Currently this is implemented entirely in the PMD as there is no explicit support in the HW. Re-program the RSS Table without this queue on stop and add it back to the table on start. Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com> Signed-off-by: Ajit Khaparde <ajit.khaparde@broadcom.com>
This commit is contained in:
parent
be160484a4
commit
9b63c6fd70
@ -202,7 +202,7 @@ static int bnxt_alloc_mem(struct bnxt *bp)
|
||||
|
||||
static int bnxt_init_chip(struct bnxt *bp)
|
||||
{
|
||||
unsigned int i, rss_idx, fw_idx;
|
||||
unsigned int i;
|
||||
struct rte_eth_link new;
|
||||
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(bp->eth_dev);
|
||||
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
|
||||
@ -279,27 +279,12 @@ static int bnxt_init_chip(struct bnxt *bp)
|
||||
i, rc);
|
||||
goto err_out;
|
||||
}
|
||||
if (vnic->rss_table && vnic->hash_type) {
|
||||
/*
|
||||
* Fill the RSS hash & redirection table with
|
||||
* ring group ids for all VNICs
|
||||
*/
|
||||
for (rss_idx = 0, fw_idx = 0;
|
||||
rss_idx < HW_HASH_INDEX_SIZE;
|
||||
rss_idx++, fw_idx++) {
|
||||
if (vnic->fw_grp_ids[fw_idx] ==
|
||||
INVALID_HW_RING_ID)
|
||||
fw_idx = 0;
|
||||
vnic->rss_table[rss_idx] =
|
||||
vnic->fw_grp_ids[fw_idx];
|
||||
}
|
||||
rc = bnxt_hwrm_vnic_rss_cfg(bp, vnic);
|
||||
if (rc) {
|
||||
PMD_DRV_LOG(ERR,
|
||||
"HWRM vnic %d set RSS failure rc: %x\n",
|
||||
i, rc);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
rc = bnxt_vnic_rss_configure(bp, vnic);
|
||||
if (rc) {
|
||||
PMD_DRV_LOG(ERR,
|
||||
"HWRM vnic set RSS failure rc: %x\n", rc);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
bnxt_hwrm_vnic_plcmode_cfg(bp, vnic);
|
||||
@ -3022,6 +3007,10 @@ static const struct eth_dev_ops bnxt_dev_ops = {
|
||||
.rx_queue_count = bnxt_rx_queue_count_op,
|
||||
.rx_descriptor_status = bnxt_rx_descriptor_status_op,
|
||||
.tx_descriptor_status = bnxt_tx_descriptor_status_op,
|
||||
.rx_queue_start = bnxt_rx_queue_start,
|
||||
.rx_queue_stop = bnxt_rx_queue_stop,
|
||||
.tx_queue_start = bnxt_tx_queue_start,
|
||||
.tx_queue_stop = bnxt_tx_queue_stop,
|
||||
.filter_ctrl = bnxt_filter_ctrl_op,
|
||||
.dev_supported_ptypes_get = bnxt_dev_supported_ptypes_get_op,
|
||||
.get_eeprom_length = bnxt_get_eeprom_length_op,
|
||||
|
@ -3676,3 +3676,31 @@ int bnxt_hwrm_clear_ntuple_filter(struct bnxt *bp,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_vnic_rss_configure(struct bnxt *bp, struct bnxt_vnic_info *vnic)
|
||||
{
|
||||
unsigned int rss_idx, fw_idx, i;
|
||||
|
||||
if (vnic->rss_table && vnic->hash_type) {
|
||||
/*
|
||||
* Fill the RSS hash & redirection table with
|
||||
* ring group ids for all VNICs
|
||||
*/
|
||||
for (rss_idx = 0, fw_idx = 0; rss_idx < HW_HASH_INDEX_SIZE;
|
||||
rss_idx++, fw_idx++) {
|
||||
for (i = 0; i < bp->rx_cp_nr_rings; i++) {
|
||||
fw_idx %= bp->rx_cp_nr_rings;
|
||||
if (vnic->fw_grp_ids[fw_idx] !=
|
||||
INVALID_HW_RING_ID)
|
||||
break;
|
||||
fw_idx++;
|
||||
}
|
||||
if (i == bp->rx_cp_nr_rings)
|
||||
return 0;
|
||||
vnic->rss_table[rss_idx] =
|
||||
vnic->fw_grp_ids[fw_idx];
|
||||
}
|
||||
return bnxt_hwrm_vnic_rss_cfg(bp, vnic);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -187,4 +187,6 @@ int bnxt_hwrm_flash_nvram(struct bnxt *bp, uint16_t dir_type,
|
||||
uint16_t dir_attr, const uint8_t *data,
|
||||
size_t data_len);
|
||||
int bnxt_hwrm_ptp_cfg(struct bnxt *bp);
|
||||
int bnxt_vnic_rss_configure(struct bnxt *bp,
|
||||
struct bnxt_vnic_info *vnic);
|
||||
#endif
|
||||
|
@ -405,3 +405,56 @@ bnxt_rx_queue_intr_disable_op(struct rte_eth_dev *eth_dev, uint16_t queue_id)
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int bnxt_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id)
|
||||
{
|
||||
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
|
||||
struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
|
||||
struct bnxt_rx_queue *rxq = bp->rx_queues[rx_queue_id];
|
||||
struct bnxt_vnic_info *vnic = NULL;
|
||||
|
||||
if (rxq == NULL) {
|
||||
PMD_DRV_LOG(ERR, "Invalid Rx queue %d\n", rx_queue_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
|
||||
rxq->rx_deferred_start = false;
|
||||
PMD_DRV_LOG(INFO, "Rx queue started %d\n", rx_queue_id);
|
||||
if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
|
||||
vnic = rxq->vnic;
|
||||
if (vnic->fw_grp_ids[rx_queue_id] != INVALID_HW_RING_ID)
|
||||
return 0;
|
||||
PMD_DRV_LOG(DEBUG, "vnic = %p fw_grp_id = %d\n",
|
||||
vnic, bp->grp_info[rx_queue_id + 1].fw_grp_id);
|
||||
vnic->fw_grp_ids[rx_queue_id] =
|
||||
bp->grp_info[rx_queue_id + 1].fw_grp_id;
|
||||
return bnxt_vnic_rss_configure(bp, vnic);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id)
|
||||
{
|
||||
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
|
||||
struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
|
||||
struct bnxt_rx_queue *rxq = bp->rx_queues[rx_queue_id];
|
||||
struct bnxt_vnic_info *vnic = NULL;
|
||||
|
||||
if (rxq == NULL) {
|
||||
PMD_DRV_LOG(ERR, "Invalid Rx queue %d\n", rx_queue_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
|
||||
rxq->rx_deferred_start = true;
|
||||
PMD_DRV_LOG(DEBUG, "Rx queue stopped\n");
|
||||
|
||||
if (dev_conf->rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG) {
|
||||
vnic = rxq->vnic;
|
||||
vnic->fw_grp_ids[rx_queue_id] = INVALID_HW_RING_ID;
|
||||
return bnxt_vnic_rss_configure(bp, vnic);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ struct bnxt_rx_queue {
|
||||
uint16_t reg_idx; /* RX queue register index */
|
||||
uint16_t port_id; /* Device port identifier */
|
||||
uint8_t crc_len; /* 0 if CRC stripped, 4 otherwise */
|
||||
uint8_t rx_deferred_start; /* not in global dev start */
|
||||
|
||||
struct bnxt *bp;
|
||||
int index;
|
||||
@ -75,5 +76,8 @@ int bnxt_rx_queue_intr_enable_op(struct rte_eth_dev *eth_dev,
|
||||
uint16_t queue_id);
|
||||
int bnxt_rx_queue_intr_disable_op(struct rte_eth_dev *eth_dev,
|
||||
uint16_t queue_id);
|
||||
|
||||
int bnxt_rx_queue_start(struct rte_eth_dev *dev,
|
||||
uint16_t rx_queue_id);
|
||||
int bnxt_rx_queue_stop(struct rte_eth_dev *dev,
|
||||
uint16_t rx_queue_id);
|
||||
#endif
|
||||
|
@ -545,6 +545,10 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
|
||||
uint16_t ag_prod = rxr->ag_prod;
|
||||
int rc = 0;
|
||||
|
||||
/* If Rx Q was stopped return */
|
||||
if (rxq->rx_deferred_start)
|
||||
return 0;
|
||||
|
||||
/* Handle RX burst request */
|
||||
while (1) {
|
||||
cons = RING_CMP(cpr->cp_ring_struct, raw_cons);
|
||||
|
@ -120,5 +120,6 @@ uint16_t bnxt_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
|
||||
void bnxt_free_rx_rings(struct bnxt *bp);
|
||||
int bnxt_init_rx_ring_struct(struct bnxt_rx_queue *rxq, unsigned int socket_id);
|
||||
int bnxt_init_one_rx_ring(struct bnxt_rx_queue *rxq);
|
||||
|
||||
int bnxt_rx_queue_start(struct rte_eth_dev *dev, uint16_t rx_queue_id);
|
||||
int bnxt_rx_queue_stop(struct rte_eth_dev *dev, uint16_t rx_queue_id);
|
||||
#endif
|
||||
|
@ -71,5 +71,4 @@ int bnxt_tx_queue_setup_op(struct rte_eth_dev *eth_dev,
|
||||
uint16_t nb_desc,
|
||||
unsigned int socket_id,
|
||||
const struct rte_eth_txconf *tx_conf);
|
||||
|
||||
#endif
|
||||
|
@ -349,6 +349,11 @@ uint16_t bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
|
||||
/* Handle TX completions */
|
||||
bnxt_handle_tx_cp(txq);
|
||||
|
||||
/* Tx queue was stopped; wait for it to be restarted */
|
||||
if (txq->tx_deferred_start) {
|
||||
PMD_DRV_LOG(DEBUG, "Tx q stopped;return\n");
|
||||
return 0;
|
||||
}
|
||||
/* Handle TX burst request */
|
||||
for (nb_tx_pkts = 0; nb_tx_pkts < nb_pkts; nb_tx_pkts++) {
|
||||
if (bnxt_start_xmit(tx_pkts[nb_tx_pkts], txq)) {
|
||||
@ -364,3 +369,30 @@ uint16_t bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
|
||||
|
||||
return nb_tx_pkts;
|
||||
}
|
||||
|
||||
int bnxt_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id)
|
||||
{
|
||||
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
|
||||
struct bnxt_tx_queue *txq = bp->tx_queues[tx_queue_id];
|
||||
|
||||
dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED;
|
||||
txq->tx_deferred_start = false;
|
||||
PMD_DRV_LOG(DEBUG, "Tx queue started\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bnxt_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id)
|
||||
{
|
||||
struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
|
||||
struct bnxt_tx_queue *txq = bp->tx_queues[tx_queue_id];
|
||||
|
||||
/* Handle TX completions */
|
||||
bnxt_handle_tx_cp(txq);
|
||||
|
||||
dev->data->tx_queue_state[tx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED;
|
||||
txq->tx_deferred_start = true;
|
||||
PMD_DRV_LOG(DEBUG, "Tx queue stopped\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ int bnxt_init_one_tx_ring(struct bnxt_tx_queue *txq);
|
||||
int bnxt_init_tx_ring_struct(struct bnxt_tx_queue *txq, unsigned int socket_id);
|
||||
uint16_t bnxt_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
|
||||
uint16_t nb_pkts);
|
||||
int bnxt_tx_queue_start(struct rte_eth_dev *dev, uint16_t tx_queue_id);
|
||||
int bnxt_tx_queue_stop(struct rte_eth_dev *dev, uint16_t tx_queue_id);
|
||||
|
||||
#define PKT_TX_OIP_IIP_TCP_UDP_CKSUM (PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM | \
|
||||
PKT_TX_IP_CKSUM | PKT_TX_OUTER_IP_CKSUM)
|
||||
|
@ -93,5 +93,4 @@ void bnxt_free_vnic_attributes(struct bnxt *bp);
|
||||
int bnxt_alloc_vnic_attributes(struct bnxt *bp);
|
||||
void bnxt_free_vnic_mem(struct bnxt *bp);
|
||||
int bnxt_alloc_vnic_mem(struct bnxt *bp);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user