net: thunderx: Support for upto 96 queues for a VF
[deliverable/linux.git] / drivers / net / ethernet / cavium / thunder / nicvf_ethtool.c
index a4228e66456707d3da44e0cfce653b318b180444..af54c10945c25175e344ebf052e47e88c62219a3 100644 (file)
@@ -35,10 +35,10 @@ struct nicvf_stat {
 }
 
 static const struct nicvf_stat nicvf_hw_stats[] = {
-       NICVF_HW_STAT(rx_bytes_ok),
-       NICVF_HW_STAT(rx_ucast_frames_ok),
-       NICVF_HW_STAT(rx_bcast_frames_ok),
-       NICVF_HW_STAT(rx_mcast_frames_ok),
+       NICVF_HW_STAT(rx_bytes),
+       NICVF_HW_STAT(rx_ucast_frames),
+       NICVF_HW_STAT(rx_bcast_frames),
+       NICVF_HW_STAT(rx_mcast_frames),
        NICVF_HW_STAT(rx_fcs_errors),
        NICVF_HW_STAT(rx_l2_errors),
        NICVF_HW_STAT(rx_drop_red),
@@ -49,6 +49,30 @@ static const struct nicvf_stat nicvf_hw_stats[] = {
        NICVF_HW_STAT(rx_drop_mcast),
        NICVF_HW_STAT(rx_drop_l3_bcast),
        NICVF_HW_STAT(rx_drop_l3_mcast),
+       NICVF_HW_STAT(rx_bgx_truncated_pkts),
+       NICVF_HW_STAT(rx_jabber_errs),
+       NICVF_HW_STAT(rx_fcs_errs),
+       NICVF_HW_STAT(rx_bgx_errs),
+       NICVF_HW_STAT(rx_prel2_errs),
+       NICVF_HW_STAT(rx_l2_hdr_malformed),
+       NICVF_HW_STAT(rx_oversize),
+       NICVF_HW_STAT(rx_undersize),
+       NICVF_HW_STAT(rx_l2_len_mismatch),
+       NICVF_HW_STAT(rx_l2_pclp),
+       NICVF_HW_STAT(rx_ip_ver_errs),
+       NICVF_HW_STAT(rx_ip_csum_errs),
+       NICVF_HW_STAT(rx_ip_hdr_malformed),
+       NICVF_HW_STAT(rx_ip_payload_malformed),
+       NICVF_HW_STAT(rx_ip_ttl_errs),
+       NICVF_HW_STAT(rx_l3_pclp),
+       NICVF_HW_STAT(rx_l4_malformed),
+       NICVF_HW_STAT(rx_l4_csum_errs),
+       NICVF_HW_STAT(rx_udp_len_errs),
+       NICVF_HW_STAT(rx_l4_port_errs),
+       NICVF_HW_STAT(rx_tcp_flag_errs),
+       NICVF_HW_STAT(rx_tcp_offset_errs),
+       NICVF_HW_STAT(rx_l4_pclp),
+       NICVF_HW_STAT(rx_truncated_pkts),
        NICVF_HW_STAT(tx_bytes_ok),
        NICVF_HW_STAT(tx_ucast_frames_ok),
        NICVF_HW_STAT(tx_bcast_frames_ok),
@@ -125,10 +149,33 @@ static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
        nic->msg_enable = lvl;
 }
 
+static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset)
+{
+       int stats, qidx;
+       int start_qidx = qset * MAX_RCV_QUEUES_PER_QS;
+
+       for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
+               for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
+                       sprintf(*data, "rxq%d: %s", qidx + start_qidx,
+                               nicvf_queue_stats[stats].name);
+                       *data += ETH_GSTRING_LEN;
+               }
+       }
+
+       for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
+               for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
+                       sprintf(*data, "txq%d: %s", qidx + start_qidx,
+                               nicvf_queue_stats[stats].name);
+                       *data += ETH_GSTRING_LEN;
+               }
+       }
+}
+
 static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 {
        struct nicvf *nic = netdev_priv(netdev);
-       int stats, qidx;
+       int stats;
+       int sqs;
 
        if (sset != ETH_SS_STATS)
                return;
@@ -143,20 +190,12 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
                data += ETH_GSTRING_LEN;
        }
 
-       for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
-               for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
-                       sprintf(data, "rxq%d: %s", qidx,
-                               nicvf_queue_stats[stats].name);
-                       data += ETH_GSTRING_LEN;
-               }
-       }
+       nicvf_get_qset_strings(nic, &data, 0);
 
-       for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
-               for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
-                       sprintf(data, "txq%d: %s", qidx,
-                               nicvf_queue_stats[stats].name);
-                       data += ETH_GSTRING_LEN;
-               }
+       for (sqs = 0; sqs < nic->sqs_count; sqs++) {
+               if (!nic->snicvf[sqs])
+                       continue;
+               nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1);
        }
 
        for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) {
@@ -173,21 +212,58 @@ static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 static int nicvf_get_sset_count(struct net_device *netdev, int sset)
 {
        struct nicvf *nic = netdev_priv(netdev);
+       int qstats_count;
+       int sqs;
 
        if (sset != ETH_SS_STATS)
                return -EINVAL;
 
+       qstats_count = nicvf_n_queue_stats *
+                      (nic->qs->rq_cnt + nic->qs->sq_cnt);
+       for (sqs = 0; sqs < nic->sqs_count; sqs++) {
+               struct nicvf *snic;
+
+               snic = nic->snicvf[sqs];
+               if (!snic)
+                       continue;
+               qstats_count += nicvf_n_queue_stats *
+                               (snic->qs->rq_cnt + snic->qs->sq_cnt);
+       }
+
        return nicvf_n_hw_stats + nicvf_n_drv_stats +
-               (nicvf_n_queue_stats *
-                (nic->qs->rq_cnt + nic->qs->sq_cnt)) +
+               qstats_count +
                BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
 }
 
+static void nicvf_get_qset_stats(struct nicvf *nic,
+                                struct ethtool_stats *stats, u64 **data)
+{
+       int stat, qidx;
+
+       if (!nic)
+               return;
+
+       for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
+               nicvf_update_rq_stats(nic, qidx);
+               for (stat = 0; stat < nicvf_n_queue_stats; stat++)
+                       *((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats)
+                                       [nicvf_queue_stats[stat].index];
+       }
+
+       for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
+               nicvf_update_sq_stats(nic, qidx);
+               for (stat = 0; stat < nicvf_n_queue_stats; stat++)
+                       *((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats)
+                                       [nicvf_queue_stats[stat].index];
+       }
+}
+
 static void nicvf_get_ethtool_stats(struct net_device *netdev,
                                    struct ethtool_stats *stats, u64 *data)
 {
        struct nicvf *nic = netdev_priv(netdev);
-       int stat, qidx;
+       int stat;
+       int sqs;
 
        nicvf_update_stats(nic);
 
@@ -195,22 +271,18 @@ static void nicvf_get_ethtool_stats(struct net_device *netdev,
        nicvf_update_lmac_stats(nic);
 
        for (stat = 0; stat < nicvf_n_hw_stats; stat++)
-               *(data++) = ((u64 *)&nic->stats)
+               *(data++) = ((u64 *)&nic->hw_stats)
                                [nicvf_hw_stats[stat].index];
        for (stat = 0; stat < nicvf_n_drv_stats; stat++)
                *(data++) = ((u64 *)&nic->drv_stats)
                                [nicvf_drv_stats[stat].index];
 
-       for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
-               for (stat = 0; stat < nicvf_n_queue_stats; stat++)
-                       *(data++) = ((u64 *)&nic->qs->rq[qidx].stats)
-                                       [nicvf_queue_stats[stat].index];
-       }
+       nicvf_get_qset_stats(nic, stats, &data);
 
-       for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
-               for (stat = 0; stat < nicvf_n_queue_stats; stat++)
-                       *(data++) = ((u64 *)&nic->qs->sq[qidx].stats)
-                                       [nicvf_queue_stats[stat].index];
+       for (sqs = 0; sqs < nic->sqs_count; sqs++) {
+               if (!nic->snicvf[sqs])
+                       continue;
+               nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data);
        }
 
        for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++)
@@ -369,7 +441,7 @@ static int nicvf_get_rxnfc(struct net_device *dev,
 
        switch (info->cmd) {
        case ETHTOOL_GRXRINGS:
-               info->data = nic->qs->rq_cnt;
+               info->data = nic->rx_queues;
                ret = 0;
                break;
        case ETHTOOL_GRXFH:
@@ -501,17 +573,15 @@ static int nicvf_set_rxfh(struct net_device *dev, const u32 *indir,
        struct nicvf_rss_info *rss = &nic->rss_info;
        int idx;
 
-       if ((nic->qs->rq_cnt <= 1) || (nic->cpi_alg != CPI_ALG_NONE)) {
-               rss->enable = false;
-               rss->hash_bits = 0;
-               return -EIO;
-       }
-
-       /* We do not allow change in unsupported parameters */
        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
                return -EOPNOTSUPP;
 
-       rss->enable = true;
+       if (!rss->enable) {
+               netdev_err(nic->netdev,
+                          "RSS is disabled, cannot change settings\n");
+               return -EIO;
+       }
+
        if (indir) {
                for (idx = 0; idx < rss->rss_size; idx++)
                        rss->ind_tbl[idx] = indir[idx];
@@ -534,11 +604,11 @@ static void nicvf_get_channels(struct net_device *dev,
 
        memset(channel, 0, sizeof(*channel));
 
-       channel->max_rx = MAX_RCV_QUEUES_PER_QS;
-       channel->max_tx = MAX_SND_QUEUES_PER_QS;
+       channel->max_rx = nic->max_queues;
+       channel->max_tx = nic->max_queues;
 
-       channel->rx_count = nic->qs->rq_cnt;
-       channel->tx_count = nic->qs->sq_cnt;
+       channel->rx_count = nic->rx_queues;
+       channel->tx_count = nic->tx_queues;
 }
 
 /* Set no of Tx, Rx queues to be used */
@@ -548,22 +618,34 @@ static int nicvf_set_channels(struct net_device *dev,
        struct nicvf *nic = netdev_priv(dev);
        int err = 0;
        bool if_up = netif_running(dev);
+       int cqcount;
 
        if (!channel->rx_count || !channel->tx_count)
                return -EINVAL;
-       if (channel->rx_count > MAX_RCV_QUEUES_PER_QS)
+       if (channel->rx_count > nic->max_queues)
                return -EINVAL;
-       if (channel->tx_count > MAX_SND_QUEUES_PER_QS)
+       if (channel->tx_count > nic->max_queues)
                return -EINVAL;
 
        if (if_up)
                nicvf_stop(dev);
 
-       nic->qs->rq_cnt = channel->rx_count;
-       nic->qs->sq_cnt = channel->tx_count;
+       cqcount = max(channel->rx_count, channel->tx_count);
+
+       if (cqcount > MAX_CMP_QUEUES_PER_QS) {
+               nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
+               nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1;
+       } else {
+               nic->sqs_count = 0;
+       }
+
+       nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS);
+       nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS);
        nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
 
-       err = nicvf_set_real_num_queues(dev, nic->qs->sq_cnt, nic->qs->rq_cnt);
+       nic->rx_queues = channel->rx_count;
+       nic->tx_queues = channel->tx_count;
+       err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
        if (err)
                return err;
 
@@ -571,7 +653,7 @@ static int nicvf_set_channels(struct net_device *dev,
                nicvf_open(dev);
 
        netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
-                   nic->qs->sq_cnt, nic->qs->rq_cnt);
+                   nic->tx_queues, nic->rx_queues);
 
        return err;
 }
This page took 0.028672 seconds and 5 git commands to generate.