root/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_link_speed
  2. hinic_get_link_ksettings
  3. hinic_get_drvinfo
  4. hinic_get_ringparam
  5. hinic_get_channels
  6. hinic_get_rss_hash_opts
  7. set_l4_rss_hash_ops
  8. hinic_set_rss_hash_opts
  9. __set_rss_rxfh
  10. hinic_get_rxnfc
  11. hinic_set_rxnfc
  12. hinic_get_rxfh
  13. hinic_set_rxfh
  14. hinic_get_rxfh_key_size
  15. hinic_get_rxfh_indir_size
  16. get_drv_queue_stats
  17. hinic_get_ethtool_stats
  18. hinic_get_sset_count
  19. hinic_get_strings
  20. hinic_set_ethtool_ops

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Huawei HiNIC PCI Express Linux driver
   3  * Copyright(c) 2017 Huawei Technologies Co., Ltd
   4  *
   5  * This program is free software; you can redistribute it and/or modify it
   6  * under the terms and conditions of the GNU General Public License,
   7  * version 2, as published by the Free Software Foundation.
   8  *
   9  * This program is distributed in the hope it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * for more details.
  13  *
  14  */
  15 
  16 #include <linux/kernel.h>
  17 #include <linux/pci.h>
  18 #include <linux/device.h>
  19 #include <linux/module.h>
  20 #include <linux/types.h>
  21 #include <linux/errno.h>
  22 #include <linux/interrupt.h>
  23 #include <linux/etherdevice.h>
  24 #include <linux/netdevice.h>
  25 #include <linux/if_vlan.h>
  26 #include <linux/ethtool.h>
  27 #include <linux/vmalloc.h>
  28 
  29 #include "hinic_hw_qp.h"
  30 #include "hinic_hw_dev.h"
  31 #include "hinic_port.h"
  32 #include "hinic_tx.h"
  33 #include "hinic_rx.h"
  34 #include "hinic_dev.h"
  35 
  36 static void set_link_speed(struct ethtool_link_ksettings *link_ksettings,
  37                            enum hinic_speed speed)
  38 {
  39         switch (speed) {
  40         case HINIC_SPEED_10MB_LINK:
  41                 link_ksettings->base.speed = SPEED_10;
  42                 break;
  43 
  44         case HINIC_SPEED_100MB_LINK:
  45                 link_ksettings->base.speed = SPEED_100;
  46                 break;
  47 
  48         case HINIC_SPEED_1000MB_LINK:
  49                 link_ksettings->base.speed = SPEED_1000;
  50                 break;
  51 
  52         case HINIC_SPEED_10GB_LINK:
  53                 link_ksettings->base.speed = SPEED_10000;
  54                 break;
  55 
  56         case HINIC_SPEED_25GB_LINK:
  57                 link_ksettings->base.speed = SPEED_25000;
  58                 break;
  59 
  60         case HINIC_SPEED_40GB_LINK:
  61                 link_ksettings->base.speed = SPEED_40000;
  62                 break;
  63 
  64         case HINIC_SPEED_100GB_LINK:
  65                 link_ksettings->base.speed = SPEED_100000;
  66                 break;
  67 
  68         default:
  69                 link_ksettings->base.speed = SPEED_UNKNOWN;
  70                 break;
  71         }
  72 }
  73 
  74 static int hinic_get_link_ksettings(struct net_device *netdev,
  75                                     struct ethtool_link_ksettings
  76                                     *link_ksettings)
  77 {
  78         struct hinic_dev *nic_dev = netdev_priv(netdev);
  79         enum hinic_port_link_state link_state;
  80         struct hinic_port_cap port_cap;
  81         int err;
  82 
  83         ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
  84         ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
  85                                              Autoneg);
  86 
  87         link_ksettings->base.speed = SPEED_UNKNOWN;
  88         link_ksettings->base.autoneg = AUTONEG_DISABLE;
  89         link_ksettings->base.duplex = DUPLEX_UNKNOWN;
  90 
  91         err = hinic_port_get_cap(nic_dev, &port_cap);
  92         if (err)
  93                 return err;
  94 
  95         err = hinic_port_link_state(nic_dev, &link_state);
  96         if (err)
  97                 return err;
  98 
  99         if (link_state != HINIC_LINK_STATE_UP)
 100                 return err;
 101 
 102         set_link_speed(link_ksettings, port_cap.speed);
 103 
 104         if (!!(port_cap.autoneg_cap & HINIC_AUTONEG_SUPPORTED))
 105                 ethtool_link_ksettings_add_link_mode(link_ksettings,
 106                                                      advertising, Autoneg);
 107 
 108         if (port_cap.autoneg_state == HINIC_AUTONEG_ACTIVE)
 109                 link_ksettings->base.autoneg = AUTONEG_ENABLE;
 110 
 111         link_ksettings->base.duplex = (port_cap.duplex == HINIC_DUPLEX_FULL) ?
 112                                            DUPLEX_FULL : DUPLEX_HALF;
 113         return 0;
 114 }
 115 
 116 static void hinic_get_drvinfo(struct net_device *netdev,
 117                               struct ethtool_drvinfo *info)
 118 {
 119         struct hinic_dev *nic_dev = netdev_priv(netdev);
 120         u8 mgmt_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
 121         struct hinic_hwdev *hwdev = nic_dev->hwdev;
 122         struct hinic_hwif *hwif = hwdev->hwif;
 123         int err;
 124 
 125         strlcpy(info->driver, HINIC_DRV_NAME, sizeof(info->driver));
 126         strlcpy(info->bus_info, pci_name(hwif->pdev), sizeof(info->bus_info));
 127 
 128         err = hinic_get_mgmt_version(nic_dev, mgmt_ver);
 129         if (err)
 130                 return;
 131 
 132         snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
 133 }
 134 
 135 static void hinic_get_ringparam(struct net_device *netdev,
 136                                 struct ethtool_ringparam *ring)
 137 {
 138         ring->rx_max_pending = HINIC_RQ_DEPTH;
 139         ring->tx_max_pending = HINIC_SQ_DEPTH;
 140         ring->rx_pending = HINIC_RQ_DEPTH;
 141         ring->tx_pending = HINIC_SQ_DEPTH;
 142 }
 143 
 144 static void hinic_get_channels(struct net_device *netdev,
 145                                struct ethtool_channels *channels)
 146 {
 147         struct hinic_dev *nic_dev = netdev_priv(netdev);
 148         struct hinic_hwdev *hwdev = nic_dev->hwdev;
 149 
 150         channels->max_rx = hwdev->nic_cap.max_qps;
 151         channels->max_tx = hwdev->nic_cap.max_qps;
 152         channels->max_other = 0;
 153         channels->max_combined = 0;
 154         channels->rx_count = hinic_hwdev_num_qps(hwdev);
 155         channels->tx_count = hinic_hwdev_num_qps(hwdev);
 156         channels->other_count = 0;
 157         channels->combined_count = 0;
 158 }
 159 
 160 static int hinic_get_rss_hash_opts(struct hinic_dev *nic_dev,
 161                                    struct ethtool_rxnfc *cmd)
 162 {
 163         struct hinic_rss_type rss_type = { 0 };
 164         int err;
 165 
 166         cmd->data = 0;
 167 
 168         if (!(nic_dev->flags & HINIC_RSS_ENABLE))
 169                 return 0;
 170 
 171         err = hinic_get_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
 172                                  &rss_type);
 173         if (err)
 174                 return err;
 175 
 176         cmd->data = RXH_IP_SRC | RXH_IP_DST;
 177         switch (cmd->flow_type) {
 178         case TCP_V4_FLOW:
 179                 if (rss_type.tcp_ipv4)
 180                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 181                 break;
 182         case TCP_V6_FLOW:
 183                 if (rss_type.tcp_ipv6)
 184                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 185                 break;
 186         case UDP_V4_FLOW:
 187                 if (rss_type.udp_ipv4)
 188                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 189                 break;
 190         case UDP_V6_FLOW:
 191                 if (rss_type.udp_ipv6)
 192                         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 193                 break;
 194         case IPV4_FLOW:
 195         case IPV6_FLOW:
 196                 break;
 197         default:
 198                 cmd->data = 0;
 199                 return -EINVAL;
 200         }
 201 
 202         return 0;
 203 }
 204 
 205 static int set_l4_rss_hash_ops(struct ethtool_rxnfc *cmd,
 206                                struct hinic_rss_type *rss_type)
 207 {
 208         u8 rss_l4_en = 0;
 209 
 210         switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 211         case 0:
 212                 rss_l4_en = 0;
 213                 break;
 214         case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 215                 rss_l4_en = 1;
 216                 break;
 217         default:
 218                 return -EINVAL;
 219         }
 220 
 221         switch (cmd->flow_type) {
 222         case TCP_V4_FLOW:
 223                 rss_type->tcp_ipv4 = rss_l4_en;
 224                 break;
 225         case TCP_V6_FLOW:
 226                 rss_type->tcp_ipv6 = rss_l4_en;
 227                 break;
 228         case UDP_V4_FLOW:
 229                 rss_type->udp_ipv4 = rss_l4_en;
 230                 break;
 231         case UDP_V6_FLOW:
 232                 rss_type->udp_ipv6 = rss_l4_en;
 233                 break;
 234         default:
 235                 return -EINVAL;
 236         }
 237 
 238         return 0;
 239 }
 240 
 241 static int hinic_set_rss_hash_opts(struct hinic_dev *nic_dev,
 242                                    struct ethtool_rxnfc *cmd)
 243 {
 244         struct hinic_rss_type *rss_type = &nic_dev->rss_type;
 245         int err;
 246 
 247         if (!(nic_dev->flags & HINIC_RSS_ENABLE)) {
 248                 cmd->data = 0;
 249                 return -EOPNOTSUPP;
 250         }
 251 
 252         /* RSS does not support anything other than hashing
 253          * to queues on src and dst IPs and ports
 254          */
 255         if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 |
 256                 RXH_L4_B_2_3))
 257                 return -EINVAL;
 258 
 259         /* We need at least the IP SRC and DEST fields for hashing */
 260         if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST))
 261                 return -EINVAL;
 262 
 263         err = hinic_get_rss_type(nic_dev,
 264                                  nic_dev->rss_tmpl_idx, rss_type);
 265         if (err)
 266                 return -EFAULT;
 267 
 268         switch (cmd->flow_type) {
 269         case TCP_V4_FLOW:
 270         case TCP_V6_FLOW:
 271         case UDP_V4_FLOW:
 272         case UDP_V6_FLOW:
 273                 err = set_l4_rss_hash_ops(cmd, rss_type);
 274                 if (err)
 275                         return err;
 276                 break;
 277         case IPV4_FLOW:
 278                 rss_type->ipv4 = 1;
 279                 break;
 280         case IPV6_FLOW:
 281                 rss_type->ipv6 = 1;
 282                 break;
 283         default:
 284                 return -EINVAL;
 285         }
 286 
 287         err = hinic_set_rss_type(nic_dev, nic_dev->rss_tmpl_idx,
 288                                  *rss_type);
 289         if (err)
 290                 return -EFAULT;
 291 
 292         return 0;
 293 }
 294 
 295 static int __set_rss_rxfh(struct net_device *netdev,
 296                           const u32 *indir, const u8 *key)
 297 {
 298         struct hinic_dev *nic_dev = netdev_priv(netdev);
 299         int err;
 300 
 301         if (indir) {
 302                 if (!nic_dev->rss_indir_user) {
 303                         nic_dev->rss_indir_user =
 304                                 kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
 305                                         GFP_KERNEL);
 306                         if (!nic_dev->rss_indir_user)
 307                                 return -ENOMEM;
 308                 }
 309 
 310                 memcpy(nic_dev->rss_indir_user, indir,
 311                        sizeof(u32) * HINIC_RSS_INDIR_SIZE);
 312 
 313                 err = hinic_rss_set_indir_tbl(nic_dev,
 314                                               nic_dev->rss_tmpl_idx, indir);
 315                 if (err)
 316                         return -EFAULT;
 317         }
 318 
 319         if (key) {
 320                 if (!nic_dev->rss_hkey_user) {
 321                         nic_dev->rss_hkey_user =
 322                                 kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
 323 
 324                         if (!nic_dev->rss_hkey_user)
 325                                 return -ENOMEM;
 326                 }
 327 
 328                 memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
 329 
 330                 err = hinic_rss_set_template_tbl(nic_dev,
 331                                                  nic_dev->rss_tmpl_idx, key);
 332                 if (err)
 333                         return -EFAULT;
 334         }
 335 
 336         return 0;
 337 }
 338 
 339 static int hinic_get_rxnfc(struct net_device *netdev,
 340                            struct ethtool_rxnfc *cmd, u32 *rule_locs)
 341 {
 342         struct hinic_dev *nic_dev = netdev_priv(netdev);
 343         int err = 0;
 344 
 345         switch (cmd->cmd) {
 346         case ETHTOOL_GRXRINGS:
 347                 cmd->data = nic_dev->num_qps;
 348                 break;
 349         case ETHTOOL_GRXFH:
 350                 err = hinic_get_rss_hash_opts(nic_dev, cmd);
 351                 break;
 352         default:
 353                 err = -EOPNOTSUPP;
 354                 break;
 355         }
 356 
 357         return err;
 358 }
 359 
 360 static int hinic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
 361 {
 362         struct hinic_dev *nic_dev = netdev_priv(netdev);
 363         int err = 0;
 364 
 365         switch (cmd->cmd) {
 366         case ETHTOOL_SRXFH:
 367                 err = hinic_set_rss_hash_opts(nic_dev, cmd);
 368                 break;
 369         default:
 370                 err = -EOPNOTSUPP;
 371                 break;
 372         }
 373 
 374         return err;
 375 }
 376 
 377 static int hinic_get_rxfh(struct net_device *netdev,
 378                           u32 *indir, u8 *key, u8 *hfunc)
 379 {
 380         struct hinic_dev *nic_dev = netdev_priv(netdev);
 381         u8 hash_engine_type = 0;
 382         int err = 0;
 383 
 384         if (!(nic_dev->flags & HINIC_RSS_ENABLE))
 385                 return -EOPNOTSUPP;
 386 
 387         if (hfunc) {
 388                 err = hinic_rss_get_hash_engine(nic_dev,
 389                                                 nic_dev->rss_tmpl_idx,
 390                                                 &hash_engine_type);
 391                 if (err)
 392                         return -EFAULT;
 393 
 394                 *hfunc = hash_engine_type ? ETH_RSS_HASH_TOP : ETH_RSS_HASH_XOR;
 395         }
 396 
 397         if (indir) {
 398                 err = hinic_rss_get_indir_tbl(nic_dev,
 399                                               nic_dev->rss_tmpl_idx, indir);
 400                 if (err)
 401                         return -EFAULT;
 402         }
 403 
 404         if (key)
 405                 err = hinic_rss_get_template_tbl(nic_dev,
 406                                                  nic_dev->rss_tmpl_idx, key);
 407 
 408         return err;
 409 }
 410 
 411 static int hinic_set_rxfh(struct net_device *netdev, const u32 *indir,
 412                           const u8 *key, const u8 hfunc)
 413 {
 414         struct hinic_dev *nic_dev = netdev_priv(netdev);
 415         int err = 0;
 416 
 417         if (!(nic_dev->flags & HINIC_RSS_ENABLE))
 418                 return -EOPNOTSUPP;
 419 
 420         if (hfunc != ETH_RSS_HASH_NO_CHANGE) {
 421                 if (hfunc != ETH_RSS_HASH_TOP && hfunc != ETH_RSS_HASH_XOR)
 422                         return -EOPNOTSUPP;
 423 
 424                 nic_dev->rss_hash_engine = (hfunc == ETH_RSS_HASH_XOR) ?
 425                         HINIC_RSS_HASH_ENGINE_TYPE_XOR :
 426                         HINIC_RSS_HASH_ENGINE_TYPE_TOEP;
 427                 err = hinic_rss_set_hash_engine
 428                         (nic_dev, nic_dev->rss_tmpl_idx,
 429                         nic_dev->rss_hash_engine);
 430                 if (err)
 431                         return -EFAULT;
 432         }
 433 
 434         err = __set_rss_rxfh(netdev, indir, key);
 435 
 436         return err;
 437 }
 438 
 439 static u32 hinic_get_rxfh_key_size(struct net_device *netdev)
 440 {
 441         return HINIC_RSS_KEY_SIZE;
 442 }
 443 
 444 static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
 445 {
 446         return HINIC_RSS_INDIR_SIZE;
 447 }
 448 
 449 #define ARRAY_LEN(arr) ((int)((int)sizeof(arr) / (int)sizeof(arr[0])))
 450 
 451 #define HINIC_FUNC_STAT(_stat_item) {   \
 452         .name = #_stat_item, \
 453         .size = FIELD_SIZEOF(struct hinic_vport_stats, _stat_item), \
 454         .offset = offsetof(struct hinic_vport_stats, _stat_item) \
 455 }
 456 
 457 static struct hinic_stats hinic_function_stats[] = {
 458         HINIC_FUNC_STAT(tx_unicast_pkts_vport),
 459         HINIC_FUNC_STAT(tx_unicast_bytes_vport),
 460         HINIC_FUNC_STAT(tx_multicast_pkts_vport),
 461         HINIC_FUNC_STAT(tx_multicast_bytes_vport),
 462         HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
 463         HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
 464 
 465         HINIC_FUNC_STAT(rx_unicast_pkts_vport),
 466         HINIC_FUNC_STAT(rx_unicast_bytes_vport),
 467         HINIC_FUNC_STAT(rx_multicast_pkts_vport),
 468         HINIC_FUNC_STAT(rx_multicast_bytes_vport),
 469         HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
 470         HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
 471 
 472         HINIC_FUNC_STAT(tx_discard_vport),
 473         HINIC_FUNC_STAT(rx_discard_vport),
 474         HINIC_FUNC_STAT(tx_err_vport),
 475         HINIC_FUNC_STAT(rx_err_vport),
 476 };
 477 
 478 #define HINIC_PORT_STAT(_stat_item) { \
 479         .name = #_stat_item, \
 480         .size = FIELD_SIZEOF(struct hinic_phy_port_stats, _stat_item), \
 481         .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
 482 }
 483 
 484 static struct hinic_stats hinic_port_stats[] = {
 485         HINIC_PORT_STAT(mac_rx_total_pkt_num),
 486         HINIC_PORT_STAT(mac_rx_total_oct_num),
 487         HINIC_PORT_STAT(mac_rx_bad_pkt_num),
 488         HINIC_PORT_STAT(mac_rx_bad_oct_num),
 489         HINIC_PORT_STAT(mac_rx_good_pkt_num),
 490         HINIC_PORT_STAT(mac_rx_good_oct_num),
 491         HINIC_PORT_STAT(mac_rx_uni_pkt_num),
 492         HINIC_PORT_STAT(mac_rx_multi_pkt_num),
 493         HINIC_PORT_STAT(mac_rx_broad_pkt_num),
 494         HINIC_PORT_STAT(mac_tx_total_pkt_num),
 495         HINIC_PORT_STAT(mac_tx_total_oct_num),
 496         HINIC_PORT_STAT(mac_tx_bad_pkt_num),
 497         HINIC_PORT_STAT(mac_tx_bad_oct_num),
 498         HINIC_PORT_STAT(mac_tx_good_pkt_num),
 499         HINIC_PORT_STAT(mac_tx_good_oct_num),
 500         HINIC_PORT_STAT(mac_tx_uni_pkt_num),
 501         HINIC_PORT_STAT(mac_tx_multi_pkt_num),
 502         HINIC_PORT_STAT(mac_tx_broad_pkt_num),
 503         HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
 504         HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
 505         HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
 506         HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
 507         HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
 508         HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
 509         HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
 510         HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
 511         HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
 512         HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
 513         HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
 514         HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
 515         HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
 516         HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
 517         HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
 518         HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
 519         HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
 520         HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
 521         HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
 522         HINIC_PORT_STAT(mac_rx_pause_num),
 523         HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
 524         HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
 525         HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
 526         HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
 527         HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
 528         HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
 529         HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
 530         HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
 531         HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
 532         HINIC_PORT_STAT(mac_rx_control_pkt_num),
 533         HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
 534         HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
 535         HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
 536         HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
 537         HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
 538         HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
 539         HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
 540         HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
 541         HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
 542         HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
 543         HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
 544         HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
 545         HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
 546         HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
 547         HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
 548         HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
 549         HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
 550         HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
 551         HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
 552         HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
 553         HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
 554         HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
 555         HINIC_PORT_STAT(mac_tx_jabber_pkt_num),
 556         HINIC_PORT_STAT(mac_tx_pause_num),
 557         HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
 558         HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
 559         HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
 560         HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
 561         HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
 562         HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
 563         HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
 564         HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
 565         HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
 566         HINIC_PORT_STAT(mac_tx_control_pkt_num),
 567         HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
 568         HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
 569         HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
 570 };
 571 
 572 #define HINIC_TXQ_STAT(_stat_item) { \
 573         .name = "txq%d_"#_stat_item, \
 574         .size = FIELD_SIZEOF(struct hinic_txq_stats, _stat_item), \
 575         .offset = offsetof(struct hinic_txq_stats, _stat_item) \
 576 }
 577 
 578 static struct hinic_stats hinic_tx_queue_stats[] = {
 579         HINIC_TXQ_STAT(pkts),
 580         HINIC_TXQ_STAT(bytes),
 581         HINIC_TXQ_STAT(tx_busy),
 582         HINIC_TXQ_STAT(tx_wake),
 583         HINIC_TXQ_STAT(tx_dropped),
 584         HINIC_TXQ_STAT(big_frags_pkts),
 585 };
 586 
 587 #define HINIC_RXQ_STAT(_stat_item) { \
 588         .name = "rxq%d_"#_stat_item, \
 589         .size = FIELD_SIZEOF(struct hinic_rxq_stats, _stat_item), \
 590         .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
 591 }
 592 
 593 static struct hinic_stats hinic_rx_queue_stats[] = {
 594         HINIC_RXQ_STAT(pkts),
 595         HINIC_RXQ_STAT(bytes),
 596         HINIC_RXQ_STAT(errors),
 597         HINIC_RXQ_STAT(csum_errors),
 598         HINIC_RXQ_STAT(other_errors),
 599 };
 600 
 601 static void get_drv_queue_stats(struct hinic_dev *nic_dev, u64 *data)
 602 {
 603         struct hinic_txq_stats txq_stats;
 604         struct hinic_rxq_stats rxq_stats;
 605         u16 i = 0, j = 0, qid = 0;
 606         char *p;
 607 
 608         for (qid = 0; qid < nic_dev->num_qps; qid++) {
 609                 if (!nic_dev->txqs)
 610                         break;
 611 
 612                 hinic_txq_get_stats(&nic_dev->txqs[qid], &txq_stats);
 613                 for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++, i++) {
 614                         p = (char *)&txq_stats +
 615                                 hinic_tx_queue_stats[j].offset;
 616                         data[i] = (hinic_tx_queue_stats[j].size ==
 617                                         sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 618                 }
 619         }
 620 
 621         for (qid = 0; qid < nic_dev->num_qps; qid++) {
 622                 if (!nic_dev->rxqs)
 623                         break;
 624 
 625                 hinic_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats);
 626                 for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++, i++) {
 627                         p = (char *)&rxq_stats +
 628                                 hinic_rx_queue_stats[j].offset;
 629                         data[i] = (hinic_rx_queue_stats[j].size ==
 630                                         sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 631                 }
 632         }
 633 }
 634 
 635 static void hinic_get_ethtool_stats(struct net_device *netdev,
 636                                     struct ethtool_stats *stats, u64 *data)
 637 {
 638         struct hinic_dev *nic_dev = netdev_priv(netdev);
 639         struct hinic_vport_stats vport_stats = {0};
 640         struct hinic_phy_port_stats *port_stats;
 641         u16 i = 0, j = 0;
 642         char *p;
 643         int err;
 644 
 645         err = hinic_get_vport_stats(nic_dev, &vport_stats);
 646         if (err)
 647                 netif_err(nic_dev, drv, netdev,
 648                           "Failed to get vport stats from firmware\n");
 649 
 650         for (j = 0; j < ARRAY_LEN(hinic_function_stats); j++, i++) {
 651                 p = (char *)&vport_stats + hinic_function_stats[j].offset;
 652                 data[i] = (hinic_function_stats[j].size ==
 653                                 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 654         }
 655 
 656         port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
 657         if (!port_stats) {
 658                 memset(&data[i], 0,
 659                        ARRAY_LEN(hinic_port_stats) * sizeof(*data));
 660                 i += ARRAY_LEN(hinic_port_stats);
 661                 goto get_drv_stats;
 662         }
 663 
 664         err = hinic_get_phy_port_stats(nic_dev, port_stats);
 665         if (err)
 666                 netif_err(nic_dev, drv, netdev,
 667                           "Failed to get port stats from firmware\n");
 668 
 669         for (j = 0; j < ARRAY_LEN(hinic_port_stats); j++, i++) {
 670                 p = (char *)port_stats + hinic_port_stats[j].offset;
 671                 data[i] = (hinic_port_stats[j].size ==
 672                                 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
 673         }
 674 
 675         kfree(port_stats);
 676 
 677 get_drv_stats:
 678         get_drv_queue_stats(nic_dev, data + i);
 679 }
 680 
 681 static int hinic_get_sset_count(struct net_device *netdev, int sset)
 682 {
 683         struct hinic_dev *nic_dev = netdev_priv(netdev);
 684         int count, q_num;
 685 
 686         switch (sset) {
 687         case ETH_SS_STATS:
 688                 q_num = nic_dev->num_qps;
 689                 count = ARRAY_LEN(hinic_function_stats) +
 690                         (ARRAY_LEN(hinic_tx_queue_stats) +
 691                         ARRAY_LEN(hinic_rx_queue_stats)) * q_num;
 692 
 693                 count += ARRAY_LEN(hinic_port_stats);
 694 
 695                 return count;
 696         default:
 697                 return -EOPNOTSUPP;
 698         }
 699 }
 700 
 701 static void hinic_get_strings(struct net_device *netdev,
 702                               u32 stringset, u8 *data)
 703 {
 704         struct hinic_dev *nic_dev = netdev_priv(netdev);
 705         char *p = (char *)data;
 706         u16 i, j;
 707 
 708         switch (stringset) {
 709         case ETH_SS_STATS:
 710                 for (i = 0; i < ARRAY_LEN(hinic_function_stats); i++) {
 711                         memcpy(p, hinic_function_stats[i].name,
 712                                ETH_GSTRING_LEN);
 713                         p += ETH_GSTRING_LEN;
 714                 }
 715 
 716                 for (i = 0; i < ARRAY_LEN(hinic_port_stats); i++) {
 717                         memcpy(p, hinic_port_stats[i].name,
 718                                ETH_GSTRING_LEN);
 719                         p += ETH_GSTRING_LEN;
 720                 }
 721 
 722                 for (i = 0; i < nic_dev->num_qps; i++) {
 723                         for (j = 0; j < ARRAY_LEN(hinic_tx_queue_stats); j++) {
 724                                 sprintf(p, hinic_tx_queue_stats[j].name, i);
 725                                 p += ETH_GSTRING_LEN;
 726                         }
 727                 }
 728 
 729                 for (i = 0; i < nic_dev->num_qps; i++) {
 730                         for (j = 0; j < ARRAY_LEN(hinic_rx_queue_stats); j++) {
 731                                 sprintf(p, hinic_rx_queue_stats[j].name, i);
 732                                 p += ETH_GSTRING_LEN;
 733                         }
 734                 }
 735 
 736                 return;
 737         default:
 738                 return;
 739         }
 740 }
 741 
 742 static const struct ethtool_ops hinic_ethtool_ops = {
 743         .get_link_ksettings = hinic_get_link_ksettings,
 744         .get_drvinfo = hinic_get_drvinfo,
 745         .get_link = ethtool_op_get_link,
 746         .get_ringparam = hinic_get_ringparam,
 747         .get_channels = hinic_get_channels,
 748         .get_rxnfc = hinic_get_rxnfc,
 749         .set_rxnfc = hinic_set_rxnfc,
 750         .get_rxfh_key_size = hinic_get_rxfh_key_size,
 751         .get_rxfh_indir_size = hinic_get_rxfh_indir_size,
 752         .get_rxfh = hinic_get_rxfh,
 753         .set_rxfh = hinic_set_rxfh,
 754         .get_sset_count = hinic_get_sset_count,
 755         .get_ethtool_stats = hinic_get_ethtool_stats,
 756         .get_strings = hinic_get_strings,
 757 };
 758 
 759 void hinic_set_ethtool_ops(struct net_device *netdev)
 760 {
 761         netdev->ethtool_ops = &hinic_ethtool_ops;
 762 }

/* [<][>][^][v][top][bottom][index][help] */