ixgbe: stats per queue
authorIntel <intel.com>
Wed, 19 Dec 2012 23:00:00 +0000 (00:00 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Thu, 25 Jul 2013 13:40:56 +0000 (15:40 +0200)
Signed-off-by: Intel
lib/librte_pmd_ixgbe/ixgbe_ethdev.c
lib/librte_pmd_ixgbe/ixgbe_ethdev.h

index 6d80456..613e49d 100644 (file)
@@ -85,6 +85,8 @@
 #define IXGBE_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */
 #define IXGBE_LINK_UP_CHECK_TIMEOUT   1000 /* ms */
 
+#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0]))
+
 static int eth_ixgbe_dev_init(struct eth_driver *eth_drv,
                struct rte_eth_dev *eth_dev);
 static int  ixgbe_dev_configure(struct rte_eth_dev *dev, uint16_t nb_rx_q,
@@ -101,6 +103,10 @@ static int ixgbe_dev_link_update(struct rte_eth_dev *dev,
 static void ixgbe_dev_stats_get(struct rte_eth_dev *dev,
                                struct rte_eth_stats *stats);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
+                                            uint16_t queue_id,
+                                            uint8_t stat_idx,
+                                            uint8_t is_rx);
 static void ixgbe_dev_info_get(struct rte_eth_dev *dev,
                                struct rte_eth_dev_info *dev_info);
 static void ixgbe_vlan_filter_set(struct rte_eth_dev *dev,
@@ -189,6 +195,7 @@ static struct eth_dev_ops ixgbe_eth_dev_ops = {
        .link_update          = ixgbe_dev_link_update,
        .stats_get            = ixgbe_dev_stats_get,
        .stats_reset          = ixgbe_dev_stats_reset,
+       .queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
        .dev_infos_get        = ixgbe_dev_info_get,
        .vlan_filter_set      = ixgbe_vlan_filter_set,
        .rx_queue_setup       = ixgbe_dev_rx_queue_setup,
@@ -326,12 +333,97 @@ static void
 ixgbe_reset_qstat_mappings(struct ixgbe_hw *hw)
 {
        uint32_t i;
-       for(i = 0; i != 16; i++) {
+
+       for(i = 0; i != IXGBE_NB_STAT_MAPPING_REGS; i++) {
                IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), 0);
                IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), 0);
        }
 }
 
+
+static int
+ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
+                                 uint16_t queue_id,
+                                 uint8_t stat_idx,
+                                 uint8_t is_rx)
+{
+#define QSM_REG_NB_BITS_PER_QMAP_FIELD 8
+#define NB_QMAP_FIELDS_PER_QSM_REG 4
+#define QMAP_FIELD_RESERVED_BITS_MASK 0x0f
+
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+       struct ixgbe_stat_mapping_registers *stat_mappings =
+               IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(eth_dev->data->dev_private);
+       uint32_t qsmr_mask = 0;
+       uint32_t clearing_mask = QMAP_FIELD_RESERVED_BITS_MASK;
+       uint32_t q_map;
+       uint8_t n, offset;
+
+       if ((hw->mac.type != ixgbe_mac_82599EB) && (hw->mac.type != ixgbe_mac_X540))
+               return -ENOSYS;
+
+       PMD_INIT_LOG(INFO, "Setting port %d, %s queue_id %d to stat index %d\n",
+                    (int)(eth_dev->data->port_id), is_rx ? "RX" : "TX", queue_id, stat_idx);
+
+       n = queue_id / NB_QMAP_FIELDS_PER_QSM_REG;
+       if (n >= IXGBE_NB_STAT_MAPPING_REGS) {
+               PMD_INIT_LOG(ERR, "Nb of stat mapping registers exceeded\n");
+               return -EIO;
+       }
+       offset = queue_id % NB_QMAP_FIELDS_PER_QSM_REG;
+
+       /* Now clear any previous stat_idx set */
+       clearing_mask <<= (QSM_REG_NB_BITS_PER_QMAP_FIELD * offset);
+       if (!is_rx)
+               stat_mappings->tqsm[n] &= ~clearing_mask;
+       else
+               stat_mappings->rqsmr[n] &= ~clearing_mask;
+
+       q_map = (uint32_t)stat_idx;
+       q_map &= QMAP_FIELD_RESERVED_BITS_MASK;
+       qsmr_mask = q_map << (QSM_REG_NB_BITS_PER_QMAP_FIELD * offset);
+       if (!is_rx)
+               stat_mappings->tqsm[n] |= qsmr_mask;
+       else
+               stat_mappings->rqsmr[n] |= qsmr_mask;
+
+       PMD_INIT_LOG(INFO, "Set port %d, %s queue_id %d to stat index %d\n"
+                    "%s[%d] = 0x%08x\n",
+                    (int)(eth_dev->data->port_id), is_rx ? "RX" : "TX", queue_id, stat_idx,
+                    is_rx ? "RQSMR" : "TQSM",n, is_rx ? stat_mappings->rqsmr[n] : stat_mappings->tqsm[n]);
+
+       /* Now write the mapping in the appropriate register */
+       if (is_rx) {
+               PMD_INIT_LOG(INFO, "Write 0x%x to RX IXGBE stat mapping reg:%d\n",
+                            stat_mappings->rqsmr[n], n);
+               IXGBE_WRITE_REG(hw, IXGBE_RQSMR(n), stat_mappings->rqsmr[n]);
+       }
+       else {
+               PMD_INIT_LOG(INFO, "Write 0x%x to TX IXGBE stat mapping reg:%d\n",
+                            stat_mappings->tqsm[n], n);
+               IXGBE_WRITE_REG(hw, IXGBE_TQSM(n), stat_mappings->tqsm[n]);
+       }
+       return 0;
+}
+
+static void
+ixgbe_restore_statistics_mapping(struct rte_eth_dev * dev)
+{
+       struct ixgbe_stat_mapping_registers *stat_mappings =
+               IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(dev->data->dev_private);
+       struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       int i;
+
+       /* write whatever was in stat mapping table to the NIC */
+       for (i = 0; i < IXGBE_NB_STAT_MAPPING_REGS; i++) {
+               /* rx */
+               IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), stat_mappings->rqsmr[i]);
+
+               /* tx */
+               IXGBE_WRITE_REG(hw, IXGBE_TQSM(i), stat_mappings->tqsm[i]);
+       }
+}
+
 /*
  * This function is based on code in ixgbe_attach() in ixgbe/ixgbe.c.
  * It returns 0 on success.
@@ -820,6 +912,8 @@ ixgbe_dev_start(struct rte_eth_dev *dev)
                        goto error;
        }
 
+       ixgbe_restore_statistics_mapping(dev);
+
        return (0);
 
 error:
@@ -927,7 +1021,7 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
                hw_stats->pxon2offc[i] +=
                    IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
        }
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) {
                hw_stats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
                hw_stats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
                hw_stats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
@@ -1034,6 +1128,14 @@ ixgbe_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
        stats->obytes = hw_stats->gotc;
        stats->imcasts = hw_stats->mprc;
 
+       for (i = 0; i < IXGBE_QUEUE_STAT_COUNTERS; i++) {
+               stats->q_ipackets[i] = hw_stats->qprc[i];
+               stats->q_opackets[i] = hw_stats->qptc[i];
+               stats->q_ibytes[i] = hw_stats->qbrc[i];
+               stats->q_obytes[i] = hw_stats->qbtc[i];
+               stats->q_errors[i] = hw_stats->qprdc[i];
+       }
+
        /* Rx Errors */
        stats->ierrors = total_missed_rx + hw_stats->crcerrs +
                hw_stats->rlec;
index 1b89738..2506d90 100644 (file)
@@ -48,7 +48,7 @@
 #define IXGBE_RXDADV_ERR_CKSUM_BIT  30
 #define IXGBE_RXDADV_ERR_CKSUM_MSK  3
 #define IXGBE_ADVTXD_MACLEN_SHIFT   9          /* Bit shift for l2_len */
-
+#define IXGBE_NB_STAT_MAPPING_REGS  32
 #define IXGBE_VFTA_SIZE 128
 
 /*
@@ -70,6 +70,11 @@ struct ixgbe_interrupt {
        uint32_t flags;
 };
 
+struct ixgbe_stat_mapping_registers {
+       uint32_t tqsm[IXGBE_NB_STAT_MAPPING_REGS];
+       uint32_t rqsmr[IXGBE_NB_STAT_MAPPING_REGS];
+};
+
 /* local VFTA copy */
 struct ixgbe_vfta {
        uint32_t vfta[IXGBE_VFTA_SIZE];
@@ -83,6 +88,7 @@ struct ixgbe_adapter {
        struct ixgbe_hw_stats       stats;
        struct ixgbe_hw_fdir_info   fdir;
        struct ixgbe_interrupt      intr;
+       struct ixgbe_stat_mapping_registers stat_mappings;
        struct ixgbe_vfta           shadow_vfta;
 };
 
@@ -98,6 +104,9 @@ struct ixgbe_adapter {
 #define IXGBE_DEV_PRIVATE_TO_FDIR_INFO(adapter) \
        (&((struct ixgbe_adapter *)adapter)->fdir)
 
+#define IXGBE_DEV_PRIVATE_TO_STAT_MAPPINGS(adapter) \
+       (&((struct ixgbe_adapter *)adapter)->stat_mappings)
+
 #define IXGBE_DEV_PRIVATE_TO_VFTA(adapter) \
        (&((struct ixgbe_adapter *)adapter)->shadow_vfta)