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:
Ajit Khaparde 2018-01-26 09:31:58 -08:00 committed by Ferruh Yigit
parent be160484a4
commit 9b63c6fd70
11 changed files with 139 additions and 26 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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