From e30e5407fd608b9d6d3925e8081638fd21cdd77a Mon Sep 17 00:00:00 2001 From: Rahul Lakkireddy Date: Sat, 12 Sep 2020 05:22:09 +0530 Subject: [PATCH] net/cxgbe: improve Rx congestion control Chelsio T6 NIC can support up to 8 priority channels to manage congestion. So, increase to 8 congestion channels for T6. Also, add Rxq state to avoid unnecessarily ringing doorbell and polling the hardware for more traffic when the Rxq is stopped. Signed-off-by: Rahul Lakkireddy --- drivers/net/cxgbe/base/adapter.h | 11 ++++++++--- drivers/net/cxgbe/base/common.h | 1 + drivers/net/cxgbe/base/t4_hw.c | 8 ++++++++ drivers/net/cxgbe/cxgbe_ethdev.c | 17 ++++++++--------- drivers/net/cxgbe/sge.c | 28 +++++++++++++++++----------- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/drivers/net/cxgbe/base/adapter.h b/drivers/net/cxgbe/base/adapter.h index f9c4cde841..6ff009a5f6 100644 --- a/drivers/net/cxgbe/base/adapter.h +++ b/drivers/net/cxgbe/base/adapter.h @@ -162,6 +162,7 @@ struct sge_eth_rx_stats { /* Ethernet rx queue statistics */ }; struct sge_eth_rxq { /* a SW Ethernet Rx queue */ + unsigned int flags; /* flags for state of the queue */ struct sge_rspq rspq; struct sge_fl fl; struct sge_eth_rx_stats stats; @@ -199,10 +200,14 @@ struct tx_sw_desc { /* SW state per Tx descriptor */ struct tx_eth_coal_desc coalesce; }; -enum { +enum cxgbe_txq_state { EQ_STOPPED = (1 << 0), }; +enum cxgbe_rxq_state { + IQ_STOPPED = (1 << 0), +}; + struct eth_coalesce { unsigned char *ptr; unsigned char type; @@ -821,8 +826,8 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *rspq, bool fwevtq, int t4_sge_eth_txq_start(struct sge_eth_txq *txq); int t4_sge_eth_txq_stop(struct sge_eth_txq *txq); void t4_sge_eth_txq_release(struct adapter *adap, struct sge_eth_txq *txq); -int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq); -int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq); +int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_eth_rxq *rxq); +int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_eth_rxq *rxq); void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq); void t4_sge_eth_clear_queues(struct port_info *pi); void t4_sge_eth_release_queues(struct port_info *pi); diff --git a/drivers/net/cxgbe/base/common.h b/drivers/net/cxgbe/base/common.h index 07508a1868..8fe8e2a36b 100644 --- a/drivers/net/cxgbe/base/common.h +++ b/drivers/net/cxgbe/base/common.h @@ -187,6 +187,7 @@ struct devlog_params { struct arch_specific_params { u8 nchan; + u8 cng_ch_bits_log; /* congestion channel map bits width */ u16 mps_rplc_size; u16 vfcount; u32 sge_fl_db; diff --git a/drivers/net/cxgbe/base/t4_hw.c b/drivers/net/cxgbe/base/t4_hw.c index 943d94fad2..9217956b42 100644 --- a/drivers/net/cxgbe/base/t4_hw.c +++ b/drivers/net/cxgbe/base/t4_hw.c @@ -5044,6 +5044,10 @@ int t4_prep_adapter(struct adapter *adapter) adapter->params.arch.mps_rplc_size = 128; adapter->params.arch.nchan = NCHAN; adapter->params.arch.vfcount = 128; + /* Congestion map is for 4 channels so that + * MPS can have 4 priority per port. + */ + adapter->params.arch.cng_ch_bits_log = 2; break; case CHELSIO_T6: adapter->params.chip |= CHELSIO_CHIP_CODE(CHELSIO_T6, pl_rev); @@ -5053,6 +5057,10 @@ int t4_prep_adapter(struct adapter *adapter) adapter->params.arch.mps_rplc_size = 256; adapter->params.arch.nchan = 2; adapter->params.arch.vfcount = 256; + /* Congestion map is for 2 channels so that + * MPS can have 8 priority per port. + */ + adapter->params.arch.cng_ch_bits_log = 3; break; default: dev_err(adapter, "%s: Device %d is not supported\n", diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c index 329b7cb5ac..b9993cb0b1 100644 --- a/drivers/net/cxgbe/cxgbe_ethdev.c +++ b/drivers/net/cxgbe/cxgbe_ethdev.c @@ -562,17 +562,16 @@ void cxgbe_dev_tx_queue_release(void *q) int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { - int ret; struct port_info *pi = eth_dev->data->dev_private; struct adapter *adap = pi->adapter; - struct sge_rspq *q; + struct sge_eth_rxq *rxq; + int ret; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); - q = eth_dev->data->rx_queues[rx_queue_id]; - - ret = t4_sge_eth_rxq_start(adap, q); + rxq = eth_dev->data->rx_queues[rx_queue_id]; + ret = t4_sge_eth_rxq_start(adap, rxq); if (ret == 0) eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STARTED; @@ -581,16 +580,16 @@ int cxgbe_dev_rx_queue_start(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) int cxgbe_dev_rx_queue_stop(struct rte_eth_dev *eth_dev, uint16_t rx_queue_id) { - int ret; struct port_info *pi = eth_dev->data->dev_private; struct adapter *adap = pi->adapter; - struct sge_rspq *q; + struct sge_eth_rxq *rxq; + int ret; dev_debug(adapter, "%s: pi->port_id = %d; rx_queue_id = %d\n", __func__, pi->port_id, rx_queue_id); - q = eth_dev->data->rx_queues[rx_queue_id]; - ret = t4_sge_eth_rxq_stop(adap, q); + rxq = eth_dev->data->rx_queues[rx_queue_id]; + ret = t4_sge_eth_rxq_stop(adap, rxq); if (ret == 0) eth_dev->data->rx_queue_state[rx_queue_id] = RTE_ETH_QUEUE_STATE_STOPPED; diff --git a/drivers/net/cxgbe/sge.c b/drivers/net/cxgbe/sge.c index 3aeef2e2f2..8c7dbe3a1d 100644 --- a/drivers/net/cxgbe/sge.c +++ b/drivers/net/cxgbe/sge.c @@ -1694,6 +1694,11 @@ int cxgbe_poll(struct sge_rspq *q, struct rte_mbuf **rx_pkts, unsigned int params; u32 val; + if (unlikely(rxq->flags & IQ_STOPPED)) { + *work_done = 0; + return 0; + } + *work_done = process_responses(q, budget, rx_pkts); if (*work_done) { @@ -1754,22 +1759,22 @@ static void __iomem *bar2_address(struct adapter *adapter, unsigned int qid, return adapter->bar2 + bar2_qoffset; } -int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_rspq *rq) +int t4_sge_eth_rxq_start(struct adapter *adap, struct sge_eth_rxq *rxq) { - struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq); unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff; + rxq->flags &= ~IQ_STOPPED; return t4_iq_start_stop(adap, adap->mbox, true, adap->pf, 0, - rq->cntxt_id, fl_id, 0xffff); + rxq->rspq.cntxt_id, fl_id, 0xffff); } -int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_rspq *rq) +int t4_sge_eth_rxq_stop(struct adapter *adap, struct sge_eth_rxq *rxq) { - struct sge_eth_rxq *rxq = container_of(rq, struct sge_eth_rxq, rspq); unsigned int fl_id = rxq->fl.size ? rxq->fl.cntxt_id : 0xffff; + rxq->flags |= IQ_STOPPED; return t4_iq_start_stop(adap, adap->mbox, false, adap->pf, 0, - rq->cntxt_id, fl_id, 0xffff); + rxq->rspq.cntxt_id, fl_id, 0xffff); } /* @@ -1949,7 +1954,8 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, * simple (and hopefully less wrong). */ if (is_pf4(adap) && !is_t4(adap->params.chip) && cong >= 0) { - u32 param, val; + u8 cng_ch_bits_log = adap->params.arch.cng_ch_bits_log; + u32 param, val, ch_map = 0; int i; param = (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) | @@ -1962,9 +1968,9 @@ int t4_sge_alloc_rxq(struct adapter *adap, struct sge_rspq *iq, bool fwevtq, X_CONMCTXT_CNGTPMODE_CHANNEL); for (i = 0; i < 4; i++) { if (cong & (1 << i)) - val |= V_CONMCTXT_CNGCHMAP(1 << - (i << 2)); + ch_map |= 1 << (i << cng_ch_bits_log); } + val |= V_CONMCTXT_CNGCHMAP(ch_map); } ret = t4_set_params(adap, adap->mbox, adap->pf, 0, 1, ¶m, &val); @@ -2201,7 +2207,7 @@ void t4_sge_eth_clear_queues(struct port_info *pi) rxq = &adap->sge.ethrxq[pi->first_rxqset]; for (i = 0; i < pi->n_rx_qsets; i++, rxq++) { if (rxq->rspq.desc) - t4_sge_eth_rxq_stop(adap, &rxq->rspq); + t4_sge_eth_rxq_stop(adap, rxq); } txq = &adap->sge.ethtxq[pi->first_txqset]; @@ -2220,7 +2226,7 @@ void t4_sge_eth_clear_queues(struct port_info *pi) void t4_sge_eth_rxq_release(struct adapter *adap, struct sge_eth_rxq *rxq) { if (rxq->rspq.desc) { - t4_sge_eth_rxq_stop(adap, &rxq->rspq); + t4_sge_eth_rxq_stop(adap, rxq); free_rspq_fl(adap, &rxq->rspq, rxq->fl.size ? &rxq->fl : NULL); } } -- 2.20.1