net: thunderx: Reset RXQ HW stats when interface is brought down
authorJerin Jacob <jerin.jacob@caviumnetworks.com>
Fri, 12 Aug 2016 11:21:39 +0000 (16:51 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sat, 13 Aug 2016 18:59:32 +0000 (11:59 -0700)
When SQ/TXQ is reclaimed i.e reset it's stats also automatically reset
by HW. This is not the case with RQ. Also VF doesn't have write access
to statistics counter registers. Hence a new Mbox msg is introduced which
supports resetting RQ, SQ and full Qset stats. Currently only RQ stats
are being reset using this mbox message.

Signed-off-by: Jerin Jacob <jerin.jacob@caviumnetworks.com>
Signed-off-by: Sunil Goutham <sgoutham@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/cavium/thunder/nic.h
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/cavium/thunder/nicvf_queues.c

index 136db2a..dd63f96 100644 (file)
@@ -347,6 +347,7 @@ struct nicvf {
 #define        NIC_MBOX_MSG_PNICVF_PTR         0x14    /* Get primary qset nicvf ptr */
 #define        NIC_MBOX_MSG_SNICVF_PTR         0x15    /* Send sqet nicvf ptr to PVF */
 #define        NIC_MBOX_MSG_LOOPBACK           0x16    /* Set interface in loopback */
+#define        NIC_MBOX_MSG_RESET_STAT_COUNTER 0x17    /* Reset statistics counters */
 #define        NIC_MBOX_MSG_CFG_DONE           0xF0    /* VF configuration done */
 #define        NIC_MBOX_MSG_SHUTDOWN           0xF1    /* VF is being shutdown */
 
@@ -463,6 +464,31 @@ struct set_loopback {
        bool  enable;
 };
 
+/* Reset statistics counters */
+struct reset_stat_cfg {
+       u8    msg;
+       /* Bitmap to select NIC_PF_VNIC(vf_id)_RX_STAT(0..13) */
+       u16   rx_stat_mask;
+       /* Bitmap to select NIC_PF_VNIC(vf_id)_TX_STAT(0..4) */
+       u8    tx_stat_mask;
+       /* Bitmap to select NIC_PF_QS(0..127)_RQ(0..7)_STAT(0..1)
+        * bit14, bit15 NIC_PF_QS(vf_id)_RQ7_STAT(0..1)
+        * bit12, bit13 NIC_PF_QS(vf_id)_RQ6_STAT(0..1)
+        * ..
+        * bit2, bit3 NIC_PF_QS(vf_id)_RQ1_STAT(0..1)
+        * bit0, bit1 NIC_PF_QS(vf_id)_RQ0_STAT(0..1)
+        */
+       u16   rq_stat_mask;
+       /* Bitmap to select NIC_PF_QS(0..127)_SQ(0..7)_STAT(0..1)
+        * bit14, bit15 NIC_PF_QS(vf_id)_SQ7_STAT(0..1)
+        * bit12, bit13 NIC_PF_QS(vf_id)_SQ6_STAT(0..1)
+        * ..
+        * bit2, bit3 NIC_PF_QS(vf_id)_SQ1_STAT(0..1)
+        * bit0, bit1 NIC_PF_QS(vf_id)_SQ0_STAT(0..1)
+        */
+       u16   sq_stat_mask;
+};
+
 /* 128 bit shared memory between PF and each VF */
 union nic_mbx {
        struct { u8 msg; }      msg;
@@ -480,6 +506,7 @@ union nic_mbx {
        struct sqs_alloc        sqs_alloc;
        struct nicvf_ptr        nicvf;
        struct set_loopback     lbk;
+       struct reset_stat_cfg   reset_stat;
 };
 
 #define NIC_NODE_ID_MASK       0x03
index c706b2e..167291b 100644 (file)
@@ -793,6 +793,48 @@ static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk)
        return 0;
 }
 
+/* Reset statistics counters */
+static int nic_reset_stat_counters(struct nicpf *nic,
+                                  int vf, struct reset_stat_cfg *cfg)
+{
+       int i, stat, qnum;
+       u64 reg_addr;
+
+       for (i = 0; i < RX_STATS_ENUM_LAST; i++) {
+               if (cfg->rx_stat_mask & BIT(i)) {
+                       reg_addr = NIC_PF_VNIC_0_127_RX_STAT_0_13 |
+                                  (vf << NIC_QS_ID_SHIFT) |
+                                  (i << 3);
+                       nic_reg_write(nic, reg_addr, 0);
+               }
+       }
+
+       for (i = 0; i < TX_STATS_ENUM_LAST; i++) {
+               if (cfg->tx_stat_mask & BIT(i)) {
+                       reg_addr = NIC_PF_VNIC_0_127_TX_STAT_0_4 |
+                                  (vf << NIC_QS_ID_SHIFT) |
+                                  (i << 3);
+                       nic_reg_write(nic, reg_addr, 0);
+               }
+       }
+
+       for (i = 0; i <= 15; i++) {
+               qnum = i >> 1;
+               stat = i & 1 ? 1 : 0;
+               reg_addr = (vf << NIC_QS_ID_SHIFT) |
+                          (qnum << NIC_Q_NUM_SHIFT) | (stat << 3);
+               if (cfg->rq_stat_mask & BIT(i)) {
+                       reg_addr |= NIC_PF_QSET_0_127_RQ_0_7_STAT_0_1;
+                       nic_reg_write(nic, reg_addr, 0);
+               }
+               if (cfg->sq_stat_mask & BIT(i)) {
+                       reg_addr |= NIC_PF_QSET_0_127_SQ_0_7_STAT_0_1;
+                       nic_reg_write(nic, reg_addr, 0);
+               }
+       }
+       return 0;
+}
+
 static void nic_enable_vf(struct nicpf *nic, int vf, bool enable)
 {
        int bgx, lmac;
@@ -942,6 +984,9 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
        case NIC_MBOX_MSG_LOOPBACK:
                ret = nic_config_loopback(nic, &mbx.lbk);
                break;
+       case NIC_MBOX_MSG_RESET_STAT_COUNTER:
+               ret = nic_reset_stat_counters(nic, vf, &mbx.reset_stat);
+               break;
        default:
                dev_err(&nic->pdev->dev,
                        "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
index ed2fe72..7d90856 100644 (file)
@@ -479,6 +479,16 @@ void nicvf_config_vlan_stripping(struct nicvf *nic, netdev_features_t features)
                                              NIC_QSET_RQ_GEN_CFG, 0, rq_cfg);
 }
 
+static void nicvf_reset_rcv_queue_stats(struct nicvf *nic)
+{
+       union nic_mbx mbx = {};
+
+       /* Reset all RXQ's stats */
+       mbx.reset_stat.msg = NIC_MBOX_MSG_RESET_STAT_COUNTER;
+       mbx.reset_stat.rq_stat_mask = 0xFFFF;
+       nicvf_send_msg_to_pf(nic, &mbx);
+}
+
 /* Configures receive queue */
 static void nicvf_rcv_queue_config(struct nicvf *nic, struct queue_set *qs,
                                   int qidx, bool enable)
@@ -812,6 +822,11 @@ int nicvf_config_data_transfer(struct nicvf *nic, bool enable)
                nicvf_free_resources(nic);
        }
 
+       /* Reset RXQ's stats.
+        * SQ's stats will get reset automatically once SQ is reset.
+        */
+       nicvf_reset_rcv_queue_stats(nic);
+
        return 0;
 }