net: thunderx: Support to configure queue sizes from ethtool
authorSunil Goutham <sgoutham@cavium.com>
Wed, 25 Jan 2017 12:06:23 +0000 (17:36 +0530)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Jan 2017 19:42:36 +0000 (14:42 -0500)
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: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.h

index 5ac474683c985cbc1fbe9b6fe4114a7d5f6c019a..02a986cdbb39cf96ed8f28c6a9326d05af60a1f3 100644 (file)
@@ -471,12 +471,46 @@ static void nicvf_get_ringparam(struct net_device *netdev,
        struct nicvf *nic = netdev_priv(netdev);
        struct queue_set *qs = nic->qs;
 
-       ring->rx_max_pending = MAX_RCV_BUF_COUNT;
-       ring->rx_pending = qs->rbdr_len;
+       ring->rx_max_pending = MAX_CMP_QUEUE_LEN;
+       ring->rx_pending = qs->cq_len;
        ring->tx_max_pending = MAX_SND_QUEUE_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,
                                   struct ethtool_rxnfc *info)
 {
@@ -787,6 +821,7 @@ static const struct ethtool_ops nicvf_ethtool_ops = {
        .get_regs               = nicvf_get_regs,
        .get_coalesce           = nicvf_get_coalesce,
        .get_ringparam          = nicvf_get_ringparam,
+       .set_ringparam          = nicvf_set_ringparam,
        .get_rxnfc              = nicvf_get_rxnfc,
        .set_rxnfc              = nicvf_set_rxnfc,
        .get_rxfh_key_size      = nicvf_get_rxfh_key_size,
index d2ac133e36f177aa548a1a5e21964737e4b1e27e..ac0390be3b126e957071bde64daebdd29b536c34 100644 (file)
@@ -603,7 +603,7 @@ void nicvf_cmp_queue_config(struct nicvf *nic, struct queue_set *qs,
        cq_cfg.ena = 1;
        cq_cfg.reset = 0;
        cq_cfg.caching = 0;
-       cq_cfg.qsize = CMP_QSIZE;
+       cq_cfg.qsize = ilog2(qs->cq_len >> 10);
        cq_cfg.avg_con = 0;
        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,
        sq_cfg.ena = 1;
        sq_cfg.reset = 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.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);
 
        /* Set threshold value for interrupt generation */
@@ -816,11 +819,21 @@ int nicvf_config_data_transfer(struct nicvf *nic, bool enable)
 {
        bool disable = false;
        struct queue_set *qs = nic->qs;
+       struct queue_set *pqs = nic->pnicvf->qs;
        int qidx;
 
        if (!qs)
                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 (nicvf_alloc_resources(nic))
                        return -ENOMEM;
index 9e2104675bc9dc0cbae020f73476d04836c01870..5cb84da99a2de5bc594464db8759c8359d20447f 100644 (file)
@@ -59,8 +59,9 @@
 /* Default queue count per QS, its lengths and threshold values */
 #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 MIN_SND_QUEUE_LEN      (1ULL << (SND_QUEUE_SIZE0 + 10))
 #define MAX_SND_QUEUE_LEN      (1ULL << (SND_QUEUE_SIZE6 + 10))
 #define SND_QUEUE_THRESH       2ULL
 #define MIN_SQ_DESC_PER_PKT_XMIT       2
 /* Keep CQ and SQ sizes same, if timestamping
  * 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 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_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 RCV_BUF_COUNT          (1ULL << (RBDR_SIZE + 13))
 #define MAX_RCV_BUF_COUNT      (1ULL << (RBDR_SIZE6 + 13))
  * RED accepts pkt if unused CQE < 2304 & >= 2560
  * DROPs pkts if unused CQE < 2304
  */
-#define RQ_PASS_CQ_LVL         160ULL
-#define RQ_DROP_CQ_LVL         144ULL
+#define RQ_PASS_CQ_LVL         192ULL
+#define RQ_DROP_CQ_LVL         184ULL
 
 /* RED and Backpressure levels of RBDR for pkt reception
  * For RBDR, level is a measure of fullness i.e 0x0 means empty