Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright 2013 Cisco Systems, Inc.  All rights reserved.
0003 
0004 #include <linux/netdevice.h>
0005 #include <linux/ethtool.h>
0006 #include <linux/net_tstamp.h>
0007 
0008 #include "enic_res.h"
0009 #include "enic.h"
0010 #include "enic_dev.h"
0011 #include "enic_clsf.h"
0012 #include "vnic_rss.h"
0013 #include "vnic_stats.h"
0014 
0015 struct enic_stat {
0016     char name[ETH_GSTRING_LEN];
0017     unsigned int index;
0018 };
0019 
0020 #define ENIC_TX_STAT(stat) { \
0021     .name = #stat, \
0022     .index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \
0023 }
0024 
0025 #define ENIC_RX_STAT(stat) { \
0026     .name = #stat, \
0027     .index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \
0028 }
0029 
0030 #define ENIC_GEN_STAT(stat) { \
0031     .name = #stat, \
0032     .index = offsetof(struct vnic_gen_stats, stat) / sizeof(u64)\
0033 }
0034 
0035 static const struct enic_stat enic_tx_stats[] = {
0036     ENIC_TX_STAT(tx_frames_ok),
0037     ENIC_TX_STAT(tx_unicast_frames_ok),
0038     ENIC_TX_STAT(tx_multicast_frames_ok),
0039     ENIC_TX_STAT(tx_broadcast_frames_ok),
0040     ENIC_TX_STAT(tx_bytes_ok),
0041     ENIC_TX_STAT(tx_unicast_bytes_ok),
0042     ENIC_TX_STAT(tx_multicast_bytes_ok),
0043     ENIC_TX_STAT(tx_broadcast_bytes_ok),
0044     ENIC_TX_STAT(tx_drops),
0045     ENIC_TX_STAT(tx_errors),
0046     ENIC_TX_STAT(tx_tso),
0047 };
0048 
0049 static const struct enic_stat enic_rx_stats[] = {
0050     ENIC_RX_STAT(rx_frames_ok),
0051     ENIC_RX_STAT(rx_frames_total),
0052     ENIC_RX_STAT(rx_unicast_frames_ok),
0053     ENIC_RX_STAT(rx_multicast_frames_ok),
0054     ENIC_RX_STAT(rx_broadcast_frames_ok),
0055     ENIC_RX_STAT(rx_bytes_ok),
0056     ENIC_RX_STAT(rx_unicast_bytes_ok),
0057     ENIC_RX_STAT(rx_multicast_bytes_ok),
0058     ENIC_RX_STAT(rx_broadcast_bytes_ok),
0059     ENIC_RX_STAT(rx_drop),
0060     ENIC_RX_STAT(rx_no_bufs),
0061     ENIC_RX_STAT(rx_errors),
0062     ENIC_RX_STAT(rx_rss),
0063     ENIC_RX_STAT(rx_crc_errors),
0064     ENIC_RX_STAT(rx_frames_64),
0065     ENIC_RX_STAT(rx_frames_127),
0066     ENIC_RX_STAT(rx_frames_255),
0067     ENIC_RX_STAT(rx_frames_511),
0068     ENIC_RX_STAT(rx_frames_1023),
0069     ENIC_RX_STAT(rx_frames_1518),
0070     ENIC_RX_STAT(rx_frames_to_max),
0071 };
0072 
0073 static const struct enic_stat enic_gen_stats[] = {
0074     ENIC_GEN_STAT(dma_map_error),
0075 };
0076 
0077 static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
0078 static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
0079 static const unsigned int enic_n_gen_stats = ARRAY_SIZE(enic_gen_stats);
0080 
0081 static void enic_intr_coal_set_rx(struct enic *enic, u32 timer)
0082 {
0083     int i;
0084     int intr;
0085 
0086     for (i = 0; i < enic->rq_count; i++) {
0087         intr = enic_msix_rq_intr(enic, i);
0088         vnic_intr_coalescing_timer_set(&enic->intr[intr], timer);
0089     }
0090 }
0091 
0092 static int enic_get_ksettings(struct net_device *netdev,
0093                   struct ethtool_link_ksettings *ecmd)
0094 {
0095     struct enic *enic = netdev_priv(netdev);
0096     struct ethtool_link_settings *base = &ecmd->base;
0097 
0098     ethtool_link_ksettings_add_link_mode(ecmd, supported,
0099                          10000baseT_Full);
0100     ethtool_link_ksettings_add_link_mode(ecmd, supported, FIBRE);
0101     ethtool_link_ksettings_add_link_mode(ecmd, advertising,
0102                          10000baseT_Full);
0103     ethtool_link_ksettings_add_link_mode(ecmd, advertising, FIBRE);
0104     base->port = PORT_FIBRE;
0105 
0106     if (netif_carrier_ok(netdev)) {
0107         base->speed = vnic_dev_port_speed(enic->vdev);
0108         base->duplex = DUPLEX_FULL;
0109     } else {
0110         base->speed = SPEED_UNKNOWN;
0111         base->duplex = DUPLEX_UNKNOWN;
0112     }
0113 
0114     base->autoneg = AUTONEG_DISABLE;
0115 
0116     return 0;
0117 }
0118 
0119 static void enic_get_drvinfo(struct net_device *netdev,
0120     struct ethtool_drvinfo *drvinfo)
0121 {
0122     struct enic *enic = netdev_priv(netdev);
0123     struct vnic_devcmd_fw_info *fw_info;
0124     int err;
0125 
0126     err = enic_dev_fw_info(enic, &fw_info);
0127     /* return only when dma_alloc_coherent fails in vnic_dev_fw_info
0128      * For other failures, like devcmd failure, we return previously
0129      * recorded info.
0130      */
0131     if (err == -ENOMEM)
0132         return;
0133 
0134     strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
0135     strlcpy(drvinfo->fw_version, fw_info->fw_version,
0136         sizeof(drvinfo->fw_version));
0137     strlcpy(drvinfo->bus_info, pci_name(enic->pdev),
0138         sizeof(drvinfo->bus_info));
0139 }
0140 
0141 static void enic_get_strings(struct net_device *netdev, u32 stringset,
0142     u8 *data)
0143 {
0144     unsigned int i;
0145 
0146     switch (stringset) {
0147     case ETH_SS_STATS:
0148         for (i = 0; i < enic_n_tx_stats; i++) {
0149             memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
0150             data += ETH_GSTRING_LEN;
0151         }
0152         for (i = 0; i < enic_n_rx_stats; i++) {
0153             memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
0154             data += ETH_GSTRING_LEN;
0155         }
0156         for (i = 0; i < enic_n_gen_stats; i++) {
0157             memcpy(data, enic_gen_stats[i].name, ETH_GSTRING_LEN);
0158             data += ETH_GSTRING_LEN;
0159         }
0160         break;
0161     }
0162 }
0163 
0164 static void enic_get_ringparam(struct net_device *netdev,
0165                    struct ethtool_ringparam *ring,
0166                    struct kernel_ethtool_ringparam *kernel_ring,
0167                    struct netlink_ext_ack *extack)
0168 {
0169     struct enic *enic = netdev_priv(netdev);
0170     struct vnic_enet_config *c = &enic->config;
0171 
0172     ring->rx_max_pending = ENIC_MAX_RQ_DESCS;
0173     ring->rx_pending = c->rq_desc_count;
0174     ring->tx_max_pending = ENIC_MAX_WQ_DESCS;
0175     ring->tx_pending = c->wq_desc_count;
0176 }
0177 
0178 static int enic_set_ringparam(struct net_device *netdev,
0179                   struct ethtool_ringparam *ring,
0180                   struct kernel_ethtool_ringparam *kernel_ring,
0181                   struct netlink_ext_ack *extack)
0182 {
0183     struct enic *enic = netdev_priv(netdev);
0184     struct vnic_enet_config *c = &enic->config;
0185     int running = netif_running(netdev);
0186     unsigned int rx_pending;
0187     unsigned int tx_pending;
0188     int err = 0;
0189 
0190     if (ring->rx_mini_max_pending || ring->rx_mini_pending) {
0191         netdev_info(netdev,
0192                 "modifying mini ring params is not supported");
0193         return -EINVAL;
0194     }
0195     if (ring->rx_jumbo_max_pending || ring->rx_jumbo_pending) {
0196         netdev_info(netdev,
0197                 "modifying jumbo ring params is not supported");
0198         return -EINVAL;
0199     }
0200     rx_pending = c->rq_desc_count;
0201     tx_pending = c->wq_desc_count;
0202     if (ring->rx_pending > ENIC_MAX_RQ_DESCS ||
0203         ring->rx_pending < ENIC_MIN_RQ_DESCS) {
0204         netdev_info(netdev, "rx pending (%u) not in range [%u,%u]",
0205                 ring->rx_pending, ENIC_MIN_RQ_DESCS,
0206                 ENIC_MAX_RQ_DESCS);
0207         return -EINVAL;
0208     }
0209     if (ring->tx_pending > ENIC_MAX_WQ_DESCS ||
0210         ring->tx_pending < ENIC_MIN_WQ_DESCS) {
0211         netdev_info(netdev, "tx pending (%u) not in range [%u,%u]",
0212                 ring->tx_pending, ENIC_MIN_WQ_DESCS,
0213                 ENIC_MAX_WQ_DESCS);
0214         return -EINVAL;
0215     }
0216     if (running)
0217         dev_close(netdev);
0218     c->rq_desc_count =
0219         ring->rx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
0220     c->wq_desc_count =
0221         ring->tx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
0222     enic_free_vnic_resources(enic);
0223     err = enic_alloc_vnic_resources(enic);
0224     if (err) {
0225         netdev_err(netdev,
0226                "Failed to alloc vNIC resources, aborting\n");
0227         enic_free_vnic_resources(enic);
0228         goto err_out;
0229     }
0230     enic_init_vnic_resources(enic);
0231     if (running) {
0232         err = dev_open(netdev, NULL);
0233         if (err)
0234             goto err_out;
0235     }
0236     return 0;
0237 err_out:
0238     c->rq_desc_count = rx_pending;
0239     c->wq_desc_count = tx_pending;
0240     return err;
0241 }
0242 
0243 static int enic_get_sset_count(struct net_device *netdev, int sset)
0244 {
0245     switch (sset) {
0246     case ETH_SS_STATS:
0247         return enic_n_tx_stats + enic_n_rx_stats + enic_n_gen_stats;
0248     default:
0249         return -EOPNOTSUPP;
0250     }
0251 }
0252 
0253 static void enic_get_ethtool_stats(struct net_device *netdev,
0254     struct ethtool_stats *stats, u64 *data)
0255 {
0256     struct enic *enic = netdev_priv(netdev);
0257     struct vnic_stats *vstats;
0258     unsigned int i;
0259     int err;
0260 
0261     err = enic_dev_stats_dump(enic, &vstats);
0262     /* return only when dma_alloc_coherent fails in vnic_dev_stats_dump
0263      * For other failures, like devcmd failure, we return previously
0264      * recorded stats.
0265      */
0266     if (err == -ENOMEM)
0267         return;
0268 
0269     for (i = 0; i < enic_n_tx_stats; i++)
0270         *(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].index];
0271     for (i = 0; i < enic_n_rx_stats; i++)
0272         *(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].index];
0273     for (i = 0; i < enic_n_gen_stats; i++)
0274         *(data++) = ((u64 *)&enic->gen_stats)[enic_gen_stats[i].index];
0275 }
0276 
0277 static u32 enic_get_msglevel(struct net_device *netdev)
0278 {
0279     struct enic *enic = netdev_priv(netdev);
0280     return enic->msg_enable;
0281 }
0282 
0283 static void enic_set_msglevel(struct net_device *netdev, u32 value)
0284 {
0285     struct enic *enic = netdev_priv(netdev);
0286     enic->msg_enable = value;
0287 }
0288 
0289 static int enic_get_coalesce(struct net_device *netdev,
0290                  struct ethtool_coalesce *ecmd,
0291                  struct kernel_ethtool_coalesce *kernel_coal,
0292                  struct netlink_ext_ack *extack)
0293 {
0294     struct enic *enic = netdev_priv(netdev);
0295     struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
0296 
0297     if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
0298         ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
0299     ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
0300     if (rxcoal->use_adaptive_rx_coalesce)
0301         ecmd->use_adaptive_rx_coalesce = 1;
0302     ecmd->rx_coalesce_usecs_low = rxcoal->small_pkt_range_start;
0303     ecmd->rx_coalesce_usecs_high = rxcoal->range_end;
0304 
0305     return 0;
0306 }
0307 
0308 static int enic_coalesce_valid(struct enic *enic,
0309                    struct ethtool_coalesce *ec)
0310 {
0311     u32 coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
0312     u32 rx_coalesce_usecs_high = min_t(u32, coalesce_usecs_max,
0313                        ec->rx_coalesce_usecs_high);
0314     u32 rx_coalesce_usecs_low = min_t(u32, coalesce_usecs_max,
0315                       ec->rx_coalesce_usecs_low);
0316 
0317     if ((vnic_dev_get_intr_mode(enic->vdev) != VNIC_DEV_INTR_MODE_MSIX) &&
0318         ec->tx_coalesce_usecs)
0319         return -EINVAL;
0320 
0321     if ((ec->tx_coalesce_usecs > coalesce_usecs_max)    ||
0322         (ec->rx_coalesce_usecs > coalesce_usecs_max)    ||
0323         (ec->rx_coalesce_usecs_low > coalesce_usecs_max)    ||
0324         (ec->rx_coalesce_usecs_high > coalesce_usecs_max))
0325         netdev_info(enic->netdev, "ethtool_set_coalesce: adaptor supports max coalesce value of %d. Setting max value.\n",
0326                 coalesce_usecs_max);
0327 
0328     if (ec->rx_coalesce_usecs_high &&
0329         (rx_coalesce_usecs_high <
0330          rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
0331         return -EINVAL;
0332 
0333     return 0;
0334 }
0335 
0336 static int enic_set_coalesce(struct net_device *netdev,
0337                  struct ethtool_coalesce *ecmd,
0338                  struct kernel_ethtool_coalesce *kernel_coal,
0339                  struct netlink_ext_ack *extack)
0340 {
0341     struct enic *enic = netdev_priv(netdev);
0342     u32 tx_coalesce_usecs;
0343     u32 rx_coalesce_usecs;
0344     u32 rx_coalesce_usecs_low;
0345     u32 rx_coalesce_usecs_high;
0346     u32 coalesce_usecs_max;
0347     unsigned int i, intr;
0348     int ret;
0349     struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
0350 
0351     ret = enic_coalesce_valid(enic, ecmd);
0352     if (ret)
0353         return ret;
0354     coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
0355     tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
0356                   coalesce_usecs_max);
0357     rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
0358                   coalesce_usecs_max);
0359 
0360     rx_coalesce_usecs_low = min_t(u32, ecmd->rx_coalesce_usecs_low,
0361                       coalesce_usecs_max);
0362     rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high,
0363                        coalesce_usecs_max);
0364 
0365     if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) {
0366         for (i = 0; i < enic->wq_count; i++) {
0367             intr = enic_msix_wq_intr(enic, i);
0368             vnic_intr_coalescing_timer_set(&enic->intr[intr],
0369                                tx_coalesce_usecs);
0370         }
0371         enic->tx_coalesce_usecs = tx_coalesce_usecs;
0372     }
0373     rxcoal->use_adaptive_rx_coalesce = !!ecmd->use_adaptive_rx_coalesce;
0374     if (!rxcoal->use_adaptive_rx_coalesce)
0375         enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
0376     if (ecmd->rx_coalesce_usecs_high) {
0377         rxcoal->range_end = rx_coalesce_usecs_high;
0378         rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
0379         rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
0380                         ENIC_AIC_LARGE_PKT_DIFF;
0381     }
0382 
0383     enic->rx_coalesce_usecs = rx_coalesce_usecs;
0384 
0385     return 0;
0386 }
0387 
0388 static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd,
0389                 u32 *rule_locs)
0390 {
0391     int j, ret = 0, cnt = 0;
0392 
0393     cmd->data = enic->rfs_h.max - enic->rfs_h.free;
0394     for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) {
0395         struct hlist_head *hhead;
0396         struct hlist_node *tmp;
0397         struct enic_rfs_fltr_node *n;
0398 
0399         hhead = &enic->rfs_h.ht_head[j];
0400         hlist_for_each_entry_safe(n, tmp, hhead, node) {
0401             if (cnt == cmd->rule_cnt)
0402                 return -EMSGSIZE;
0403             rule_locs[cnt] = n->fltr_id;
0404             cnt++;
0405         }
0406     }
0407     cmd->rule_cnt = cnt;
0408 
0409     return ret;
0410 }
0411 
0412 static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
0413 {
0414     struct ethtool_rx_flow_spec *fsp =
0415                 (struct ethtool_rx_flow_spec *)&cmd->fs;
0416     struct enic_rfs_fltr_node *n;
0417 
0418     n = htbl_fltr_search(enic, (u16)fsp->location);
0419     if (!n)
0420         return -EINVAL;
0421     switch (n->keys.basic.ip_proto) {
0422     case IPPROTO_TCP:
0423         fsp->flow_type = TCP_V4_FLOW;
0424         break;
0425     case IPPROTO_UDP:
0426         fsp->flow_type = UDP_V4_FLOW;
0427         break;
0428     default:
0429         return -EINVAL;
0430     }
0431 
0432     fsp->h_u.tcp_ip4_spec.ip4src = flow_get_u32_src(&n->keys);
0433     fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
0434 
0435     fsp->h_u.tcp_ip4_spec.ip4dst = flow_get_u32_dst(&n->keys);
0436     fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
0437 
0438     fsp->h_u.tcp_ip4_spec.psrc = n->keys.ports.src;
0439     fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
0440 
0441     fsp->h_u.tcp_ip4_spec.pdst = n->keys.ports.dst;
0442     fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
0443 
0444     fsp->ring_cookie = n->rq_id;
0445 
0446     return 0;
0447 }
0448 
0449 static int enic_get_rx_flow_hash(struct enic *enic, struct ethtool_rxnfc *cmd)
0450 {
0451     u8 rss_hash_type = 0;
0452     cmd->data = 0;
0453 
0454     spin_lock_bh(&enic->devcmd_lock);
0455     (void)vnic_dev_capable_rss_hash_type(enic->vdev, &rss_hash_type);
0456     spin_unlock_bh(&enic->devcmd_lock);
0457     switch (cmd->flow_type) {
0458     case TCP_V6_FLOW:
0459     case TCP_V4_FLOW:
0460         cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
0461                  RXH_IP_SRC | RXH_IP_DST;
0462         break;
0463     case UDP_V6_FLOW:
0464         cmd->data |= RXH_IP_SRC | RXH_IP_DST;
0465         if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV6)
0466             cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
0467         break;
0468     case UDP_V4_FLOW:
0469         cmd->data |= RXH_IP_SRC | RXH_IP_DST;
0470         if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV4)
0471             cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
0472         break;
0473     case SCTP_V4_FLOW:
0474     case AH_ESP_V4_FLOW:
0475     case AH_V4_FLOW:
0476     case ESP_V4_FLOW:
0477     case SCTP_V6_FLOW:
0478     case AH_ESP_V6_FLOW:
0479     case AH_V6_FLOW:
0480     case ESP_V6_FLOW:
0481     case IPV4_FLOW:
0482     case IPV6_FLOW:
0483         cmd->data |= RXH_IP_SRC | RXH_IP_DST;
0484         break;
0485     default:
0486         return -EINVAL;
0487     }
0488 
0489     return 0;
0490 }
0491 
0492 static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
0493               u32 *rule_locs)
0494 {
0495     struct enic *enic = netdev_priv(dev);
0496     int ret = 0;
0497 
0498     switch (cmd->cmd) {
0499     case ETHTOOL_GRXRINGS:
0500         cmd->data = enic->rq_count;
0501         break;
0502     case ETHTOOL_GRXCLSRLCNT:
0503         spin_lock_bh(&enic->rfs_h.lock);
0504         cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free;
0505         cmd->data = enic->rfs_h.max;
0506         spin_unlock_bh(&enic->rfs_h.lock);
0507         break;
0508     case ETHTOOL_GRXCLSRLALL:
0509         spin_lock_bh(&enic->rfs_h.lock);
0510         ret = enic_grxclsrlall(enic, cmd, rule_locs);
0511         spin_unlock_bh(&enic->rfs_h.lock);
0512         break;
0513     case ETHTOOL_GRXCLSRULE:
0514         spin_lock_bh(&enic->rfs_h.lock);
0515         ret = enic_grxclsrule(enic, cmd);
0516         spin_unlock_bh(&enic->rfs_h.lock);
0517         break;
0518     case ETHTOOL_GRXFH:
0519         ret = enic_get_rx_flow_hash(enic, cmd);
0520         break;
0521     default:
0522         ret = -EOPNOTSUPP;
0523         break;
0524     }
0525 
0526     return ret;
0527 }
0528 
0529 static int enic_get_tunable(struct net_device *dev,
0530                 const struct ethtool_tunable *tuna, void *data)
0531 {
0532     struct enic *enic = netdev_priv(dev);
0533     int ret = 0;
0534 
0535     switch (tuna->id) {
0536     case ETHTOOL_RX_COPYBREAK:
0537         *(u32 *)data = enic->rx_copybreak;
0538         break;
0539     default:
0540         ret = -EINVAL;
0541         break;
0542     }
0543 
0544     return ret;
0545 }
0546 
0547 static int enic_set_tunable(struct net_device *dev,
0548                 const struct ethtool_tunable *tuna,
0549                 const void *data)
0550 {
0551     struct enic *enic = netdev_priv(dev);
0552     int ret = 0;
0553 
0554     switch (tuna->id) {
0555     case ETHTOOL_RX_COPYBREAK:
0556         enic->rx_copybreak = *(u32 *)data;
0557         break;
0558     default:
0559         ret = -EINVAL;
0560         break;
0561     }
0562 
0563     return ret;
0564 }
0565 
0566 static u32 enic_get_rxfh_key_size(struct net_device *netdev)
0567 {
0568     return ENIC_RSS_LEN;
0569 }
0570 
0571 static int enic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey,
0572              u8 *hfunc)
0573 {
0574     struct enic *enic = netdev_priv(netdev);
0575 
0576     if (hkey)
0577         memcpy(hkey, enic->rss_key, ENIC_RSS_LEN);
0578 
0579     if (hfunc)
0580         *hfunc = ETH_RSS_HASH_TOP;
0581 
0582     return 0;
0583 }
0584 
0585 static int enic_set_rxfh(struct net_device *netdev, const u32 *indir,
0586              const u8 *hkey, const u8 hfunc)
0587 {
0588     struct enic *enic = netdev_priv(netdev);
0589 
0590     if ((hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) ||
0591         indir)
0592         return -EINVAL;
0593 
0594     if (hkey)
0595         memcpy(enic->rss_key, hkey, ENIC_RSS_LEN);
0596 
0597     return __enic_set_rsskey(enic);
0598 }
0599 
0600 static int enic_get_ts_info(struct net_device *netdev,
0601                 struct ethtool_ts_info *info)
0602 {
0603     info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
0604                 SOF_TIMESTAMPING_RX_SOFTWARE |
0605                 SOF_TIMESTAMPING_SOFTWARE;
0606 
0607     return 0;
0608 }
0609 
0610 static const struct ethtool_ops enic_ethtool_ops = {
0611     .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
0612                      ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
0613                      ETHTOOL_COALESCE_RX_USECS_LOW |
0614                      ETHTOOL_COALESCE_RX_USECS_HIGH,
0615     .get_drvinfo = enic_get_drvinfo,
0616     .get_msglevel = enic_get_msglevel,
0617     .set_msglevel = enic_set_msglevel,
0618     .get_link = ethtool_op_get_link,
0619     .get_strings = enic_get_strings,
0620     .get_ringparam = enic_get_ringparam,
0621     .set_ringparam = enic_set_ringparam,
0622     .get_sset_count = enic_get_sset_count,
0623     .get_ethtool_stats = enic_get_ethtool_stats,
0624     .get_coalesce = enic_get_coalesce,
0625     .set_coalesce = enic_set_coalesce,
0626     .get_rxnfc = enic_get_rxnfc,
0627     .get_tunable = enic_get_tunable,
0628     .set_tunable = enic_set_tunable,
0629     .get_rxfh_key_size = enic_get_rxfh_key_size,
0630     .get_rxfh = enic_get_rxfh,
0631     .set_rxfh = enic_set_rxfh,
0632     .get_link_ksettings = enic_get_ksettings,
0633     .get_ts_info = enic_get_ts_info,
0634 };
0635 
0636 void enic_set_ethtool_ops(struct net_device *netdev)
0637 {
0638     netdev->ethtool_ops = &enic_ethtool_ops;
0639 }