Commit fff4ffdd authored by Sunil Goutham's avatar Sunil Goutham Committed by David S. Miller

net: thunderx: Support to configure queue sizes from ethtool

Adds support to set Rx/Tx queue sizes from ethtool. Fixes
an issue with retrieving queue size. Also sets SQ's CQ_LIMIT
based on configured Tx queue size such that HW doesn't process
SQEs when there is no sufficient space in CQ.
Signed-off-by: default avatarSunil Goutham <sgoutham@cavium.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3979ad7e
...@@ -471,12 +471,46 @@ static void nicvf_get_ringparam(struct net_device *netdev, ...@@ -471,12 +471,46 @@ static void nicvf_get_ringparam(struct net_device *netdev,
struct nicvf *nic = netdev_priv(netdev); struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs; struct queue_set *qs = nic->qs;
ring->rx_max_pending = MAX_RCV_BUF_COUNT; ring->rx_max_pending = MAX_CMP_QUEUE_LEN;
ring->rx_pending = qs->rbdr_len; ring->rx_pending = qs->cq_len;
ring->tx_max_pending = MAX_SND_QUEUE_LEN; ring->tx_max_pending = MAX_SND_QUEUE_LEN;
ring->tx_pending = qs->sq_len; ring->tx_pending = qs->sq_len;
} }
static int nicvf_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
u32 rx_count, tx_count;
/* Due to HW errata this is not supported on T88 pass 1.x silicon */
if (pass1_silicon(nic->pdev))
return -EINVAL;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
tx_count = clamp_t(u32, ring->tx_pending,
MIN_SND_QUEUE_LEN, MAX_SND_QUEUE_LEN);
rx_count = clamp_t(u32, ring->rx_pending,
MIN_CMP_QUEUE_LEN, MAX_CMP_QUEUE_LEN);
if ((tx_count == qs->sq_len) && (rx_count == qs->cq_len))
return 0;
/* Permitted lengths are 1K, 2K, 4K, 8K, 16K, 32K, 64K */
qs->sq_len = rounddown_pow_of_two(tx_count);
qs->cq_len = rounddown_pow_of_two(rx_count);
if (netif_running(netdev)) {
nicvf_stop(netdev);
nicvf_open(netdev);
}
return 0;
}
static int nicvf_get_rss_hash_opts(struct nicvf *nic, static int nicvf_get_rss_hash_opts(struct nicvf *nic,
struct ethtool_rxnfc *info) struct ethtool_rxnfc *info)
{ {
...@@ -787,6 +821,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = { ...@@ -787,6 +821,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
.get_regs = nicvf_get_regs, .get_regs = nicvf_get_regs,
.get_coalesce = nicvf_get_coalesce, .get_coalesce = nicvf_get_coalesce,
.get_ringparam = nicvf_get_ringparam, .get_ringparam = nicvf_get_ringparam,
.set_ringparam = nicvf_set_ringparam,
.get_rxnfc = nicvf_get_rxnfc, .get_rxnfc = nicvf_get_rxnfc,
.set_rxnfc = nicvf_set_rxnfc, .set_rxnfc = nicvf_set_rxnfc,
.get_rxfh_key_size = nicvf_get_rxfh_key_size, .get_rxfh_key_size = nicvf_get_rxfh_key_size,
......
...@@ -603,7 +603,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -603,7 +603,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
cq_cfg.ena = 1; cq_cfg.ena = 1;
cq_cfg.reset = 0; cq_cfg.reset = 0;
cq_cfg.caching = 0; cq_cfg.caching = 0;
cq_cfg.qsize = CMP_QSIZE; cq_cfg.qsize = ilog2(qs->cq_len >> 10);
cq_cfg.avg_con = 0; cq_cfg.avg_con = 0;
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, *(u64 *)&cq_cfg); nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_CFG, qidx, *(u64 *)&cq_cfg);
...@@ -652,9 +652,12 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs, ...@@ -652,9 +652,12 @@ static void nicvf_snd_queue_config(struct nicvf *nic, struct queue_set *qs,
sq_cfg.ena = 1; sq_cfg.ena = 1;
sq_cfg.reset = 0; sq_cfg.reset = 0;
sq_cfg.ldwb = 0; sq_cfg.ldwb = 0;
sq_cfg.qsize = SND_QSIZE; sq_cfg.qsize = ilog2(qs->sq_len >> 10);
sq_cfg.tstmp_bgx_intf = 0; sq_cfg.tstmp_bgx_intf = 0;
sq_cfg.cq_limit = 0; /* CQ's level at which HW will stop processing SQEs to avoid
* transmitting a pkt with no space in CQ to post CQE_TX.
*/
sq_cfg.cq_limit = (CMP_QUEUE_PIPELINE_RSVD * 256) / qs->cq_len;
nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, *(u64 *)&sq_cfg); nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_CFG, qidx, *(u64 *)&sq_cfg);
/* Set threshold value for interrupt generation */ /* Set threshold value for interrupt generation */
...@@ -816,11 +819,21 @@ int nicvf_config_data_transfer(struct nicvf *nic, bool enable) ...@@ -816,11 +819,21 @@ int nicvf_config_data_transfer(struct nicvf *nic, bool enable)
{ {
bool disable = false; bool disable = false;
struct queue_set *qs = nic->qs; struct queue_set *qs = nic->qs;
struct queue_set *pqs = nic->pnicvf->qs;
int qidx; int qidx;
if (!qs) if (!qs)
return 0; return 0;
/* Take primary VF's queue lengths.
* This is needed to take queue lengths set from ethtool
* into consideration.
*/
if (nic->sqs_mode && pqs) {
qs->cq_len = pqs->cq_len;
qs->sq_len = pqs->sq_len;
}
if (enable) { if (enable) {
if (nicvf_alloc_resources(nic)) if (nicvf_alloc_resources(nic))
return -ENOMEM; return -ENOMEM;
......
...@@ -59,8 +59,9 @@ ...@@ -59,8 +59,9 @@
/* Default queue count per QS, its lengths and threshold values */ /* Default queue count per QS, its lengths and threshold values */
#define DEFAULT_RBDR_CNT 1 #define DEFAULT_RBDR_CNT 1
#define SND_QSIZE SND_QUEUE_SIZE2 #define SND_QSIZE SND_QUEUE_SIZE0
#define SND_QUEUE_LEN (1ULL << (SND_QSIZE + 10)) #define SND_QUEUE_LEN (1ULL << (SND_QSIZE + 10))
#define MIN_SND_QUEUE_LEN (1ULL << (SND_QUEUE_SIZE0 + 10))
#define MAX_SND_QUEUE_LEN (1ULL << (SND_QUEUE_SIZE6 + 10)) #define MAX_SND_QUEUE_LEN (1ULL << (SND_QUEUE_SIZE6 + 10))
#define SND_QUEUE_THRESH 2ULL #define SND_QUEUE_THRESH 2ULL
#define MIN_SQ_DESC_PER_PKT_XMIT 2 #define MIN_SQ_DESC_PER_PKT_XMIT 2
...@@ -70,11 +71,18 @@ ...@@ -70,11 +71,18 @@
/* Keep CQ and SQ sizes same, if timestamping /* Keep CQ and SQ sizes same, if timestamping
* is enabled this equation will change. * is enabled this equation will change.
*/ */
#define CMP_QSIZE CMP_QUEUE_SIZE2 #define CMP_QSIZE CMP_QUEUE_SIZE0
#define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10)) #define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10))
#define MIN_CMP_QUEUE_LEN (1ULL << (CMP_QUEUE_SIZE0 + 10))
#define MAX_CMP_QUEUE_LEN (1ULL << (CMP_QUEUE_SIZE6 + 10))
#define CMP_QUEUE_CQE_THRESH (NAPI_POLL_WEIGHT / 2) #define CMP_QUEUE_CQE_THRESH (NAPI_POLL_WEIGHT / 2)
#define CMP_QUEUE_TIMER_THRESH 80 /* ~2usec */ #define CMP_QUEUE_TIMER_THRESH 80 /* ~2usec */
/* No of CQEs that might anyway gets used by HW due to pipelining
* effects irrespective of PASS/DROP/LEVELS being configured
*/
#define CMP_QUEUE_PIPELINE_RSVD 544
#define RBDR_SIZE RBDR_SIZE0 #define RBDR_SIZE RBDR_SIZE0
#define RCV_BUF_COUNT (1ULL << (RBDR_SIZE + 13)) #define RCV_BUF_COUNT (1ULL << (RBDR_SIZE + 13))
#define MAX_RCV_BUF_COUNT (1ULL << (RBDR_SIZE6 + 13)) #define MAX_RCV_BUF_COUNT (1ULL << (RBDR_SIZE6 + 13))
...@@ -93,8 +101,8 @@ ...@@ -93,8 +101,8 @@
* RED accepts pkt if unused CQE < 2304 & >= 2560 * RED accepts pkt if unused CQE < 2304 & >= 2560
* DROPs pkts if unused CQE < 2304 * DROPs pkts if unused CQE < 2304
*/ */
#define RQ_PASS_CQ_LVL 160ULL #define RQ_PASS_CQ_LVL 192ULL
#define RQ_DROP_CQ_LVL 144ULL #define RQ_DROP_CQ_LVL 184ULL
/* RED and Backpressure levels of RBDR for pkt reception /* RED and Backpressure levels of RBDR for pkt reception
* For RBDR, level is a measure of fullness i.e 0x0 means empty * For RBDR, level is a measure of fullness i.e 0x0 means empty
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment