cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

enic_ethtool.c (17848B)


      1/*
      2 * Copyright 2013 Cisco Systems, Inc.  All rights reserved.
      3 *
      4 * This program is free software; you may redistribute it and/or modify
      5 * it under the terms of the GNU General Public License as published by
      6 * the Free Software Foundation; version 2 of the License.
      7 *
      8 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
      9 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     10 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     11 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     12 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     13 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     14 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     15 * SOFTWARE.
     16 *
     17 */
     18
     19#include <linux/netdevice.h>
     20#include <linux/ethtool.h>
     21#include <linux/net_tstamp.h>
     22
     23#include "enic_res.h"
     24#include "enic.h"
     25#include "enic_dev.h"
     26#include "enic_clsf.h"
     27#include "vnic_rss.h"
     28#include "vnic_stats.h"
     29
     30struct enic_stat {
     31	char name[ETH_GSTRING_LEN];
     32	unsigned int index;
     33};
     34
     35#define ENIC_TX_STAT(stat) { \
     36	.name = #stat, \
     37	.index = offsetof(struct vnic_tx_stats, stat) / sizeof(u64) \
     38}
     39
     40#define ENIC_RX_STAT(stat) { \
     41	.name = #stat, \
     42	.index = offsetof(struct vnic_rx_stats, stat) / sizeof(u64) \
     43}
     44
     45#define ENIC_GEN_STAT(stat) { \
     46	.name = #stat, \
     47	.index = offsetof(struct vnic_gen_stats, stat) / sizeof(u64)\
     48}
     49
     50static const struct enic_stat enic_tx_stats[] = {
     51	ENIC_TX_STAT(tx_frames_ok),
     52	ENIC_TX_STAT(tx_unicast_frames_ok),
     53	ENIC_TX_STAT(tx_multicast_frames_ok),
     54	ENIC_TX_STAT(tx_broadcast_frames_ok),
     55	ENIC_TX_STAT(tx_bytes_ok),
     56	ENIC_TX_STAT(tx_unicast_bytes_ok),
     57	ENIC_TX_STAT(tx_multicast_bytes_ok),
     58	ENIC_TX_STAT(tx_broadcast_bytes_ok),
     59	ENIC_TX_STAT(tx_drops),
     60	ENIC_TX_STAT(tx_errors),
     61	ENIC_TX_STAT(tx_tso),
     62};
     63
     64static const struct enic_stat enic_rx_stats[] = {
     65	ENIC_RX_STAT(rx_frames_ok),
     66	ENIC_RX_STAT(rx_frames_total),
     67	ENIC_RX_STAT(rx_unicast_frames_ok),
     68	ENIC_RX_STAT(rx_multicast_frames_ok),
     69	ENIC_RX_STAT(rx_broadcast_frames_ok),
     70	ENIC_RX_STAT(rx_bytes_ok),
     71	ENIC_RX_STAT(rx_unicast_bytes_ok),
     72	ENIC_RX_STAT(rx_multicast_bytes_ok),
     73	ENIC_RX_STAT(rx_broadcast_bytes_ok),
     74	ENIC_RX_STAT(rx_drop),
     75	ENIC_RX_STAT(rx_no_bufs),
     76	ENIC_RX_STAT(rx_errors),
     77	ENIC_RX_STAT(rx_rss),
     78	ENIC_RX_STAT(rx_crc_errors),
     79	ENIC_RX_STAT(rx_frames_64),
     80	ENIC_RX_STAT(rx_frames_127),
     81	ENIC_RX_STAT(rx_frames_255),
     82	ENIC_RX_STAT(rx_frames_511),
     83	ENIC_RX_STAT(rx_frames_1023),
     84	ENIC_RX_STAT(rx_frames_1518),
     85	ENIC_RX_STAT(rx_frames_to_max),
     86};
     87
     88static const struct enic_stat enic_gen_stats[] = {
     89	ENIC_GEN_STAT(dma_map_error),
     90};
     91
     92static const unsigned int enic_n_tx_stats = ARRAY_SIZE(enic_tx_stats);
     93static const unsigned int enic_n_rx_stats = ARRAY_SIZE(enic_rx_stats);
     94static const unsigned int enic_n_gen_stats = ARRAY_SIZE(enic_gen_stats);
     95
     96static void enic_intr_coal_set_rx(struct enic *enic, u32 timer)
     97{
     98	int i;
     99	int intr;
    100
    101	for (i = 0; i < enic->rq_count; i++) {
    102		intr = enic_msix_rq_intr(enic, i);
    103		vnic_intr_coalescing_timer_set(&enic->intr[intr], timer);
    104	}
    105}
    106
    107static int enic_get_ksettings(struct net_device *netdev,
    108			      struct ethtool_link_ksettings *ecmd)
    109{
    110	struct enic *enic = netdev_priv(netdev);
    111	struct ethtool_link_settings *base = &ecmd->base;
    112
    113	ethtool_link_ksettings_add_link_mode(ecmd, supported,
    114					     10000baseT_Full);
    115	ethtool_link_ksettings_add_link_mode(ecmd, supported, FIBRE);
    116	ethtool_link_ksettings_add_link_mode(ecmd, advertising,
    117					     10000baseT_Full);
    118	ethtool_link_ksettings_add_link_mode(ecmd, advertising, FIBRE);
    119	base->port = PORT_FIBRE;
    120
    121	if (netif_carrier_ok(netdev)) {
    122		base->speed = vnic_dev_port_speed(enic->vdev);
    123		base->duplex = DUPLEX_FULL;
    124	} else {
    125		base->speed = SPEED_UNKNOWN;
    126		base->duplex = DUPLEX_UNKNOWN;
    127	}
    128
    129	base->autoneg = AUTONEG_DISABLE;
    130
    131	return 0;
    132}
    133
    134static void enic_get_drvinfo(struct net_device *netdev,
    135	struct ethtool_drvinfo *drvinfo)
    136{
    137	struct enic *enic = netdev_priv(netdev);
    138	struct vnic_devcmd_fw_info *fw_info;
    139	int err;
    140
    141	err = enic_dev_fw_info(enic, &fw_info);
    142	/* return only when dma_alloc_coherent fails in vnic_dev_fw_info
    143	 * For other failures, like devcmd failure, we return previously
    144	 * recorded info.
    145	 */
    146	if (err == -ENOMEM)
    147		return;
    148
    149	strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
    150	strlcpy(drvinfo->fw_version, fw_info->fw_version,
    151		sizeof(drvinfo->fw_version));
    152	strlcpy(drvinfo->bus_info, pci_name(enic->pdev),
    153		sizeof(drvinfo->bus_info));
    154}
    155
    156static void enic_get_strings(struct net_device *netdev, u32 stringset,
    157	u8 *data)
    158{
    159	unsigned int i;
    160
    161	switch (stringset) {
    162	case ETH_SS_STATS:
    163		for (i = 0; i < enic_n_tx_stats; i++) {
    164			memcpy(data, enic_tx_stats[i].name, ETH_GSTRING_LEN);
    165			data += ETH_GSTRING_LEN;
    166		}
    167		for (i = 0; i < enic_n_rx_stats; i++) {
    168			memcpy(data, enic_rx_stats[i].name, ETH_GSTRING_LEN);
    169			data += ETH_GSTRING_LEN;
    170		}
    171		for (i = 0; i < enic_n_gen_stats; i++) {
    172			memcpy(data, enic_gen_stats[i].name, ETH_GSTRING_LEN);
    173			data += ETH_GSTRING_LEN;
    174		}
    175		break;
    176	}
    177}
    178
    179static void enic_get_ringparam(struct net_device *netdev,
    180			       struct ethtool_ringparam *ring,
    181			       struct kernel_ethtool_ringparam *kernel_ring,
    182			       struct netlink_ext_ack *extack)
    183{
    184	struct enic *enic = netdev_priv(netdev);
    185	struct vnic_enet_config *c = &enic->config;
    186
    187	ring->rx_max_pending = ENIC_MAX_RQ_DESCS;
    188	ring->rx_pending = c->rq_desc_count;
    189	ring->tx_max_pending = ENIC_MAX_WQ_DESCS;
    190	ring->tx_pending = c->wq_desc_count;
    191}
    192
    193static int enic_set_ringparam(struct net_device *netdev,
    194			      struct ethtool_ringparam *ring,
    195			      struct kernel_ethtool_ringparam *kernel_ring,
    196			      struct netlink_ext_ack *extack)
    197{
    198	struct enic *enic = netdev_priv(netdev);
    199	struct vnic_enet_config *c = &enic->config;
    200	int running = netif_running(netdev);
    201	unsigned int rx_pending;
    202	unsigned int tx_pending;
    203	int err = 0;
    204
    205	if (ring->rx_mini_max_pending || ring->rx_mini_pending) {
    206		netdev_info(netdev,
    207			    "modifying mini ring params is not supported");
    208		return -EINVAL;
    209	}
    210	if (ring->rx_jumbo_max_pending || ring->rx_jumbo_pending) {
    211		netdev_info(netdev,
    212			    "modifying jumbo ring params is not supported");
    213		return -EINVAL;
    214	}
    215	rx_pending = c->rq_desc_count;
    216	tx_pending = c->wq_desc_count;
    217	if (ring->rx_pending > ENIC_MAX_RQ_DESCS ||
    218	    ring->rx_pending < ENIC_MIN_RQ_DESCS) {
    219		netdev_info(netdev, "rx pending (%u) not in range [%u,%u]",
    220			    ring->rx_pending, ENIC_MIN_RQ_DESCS,
    221			    ENIC_MAX_RQ_DESCS);
    222		return -EINVAL;
    223	}
    224	if (ring->tx_pending > ENIC_MAX_WQ_DESCS ||
    225	    ring->tx_pending < ENIC_MIN_WQ_DESCS) {
    226		netdev_info(netdev, "tx pending (%u) not in range [%u,%u]",
    227			    ring->tx_pending, ENIC_MIN_WQ_DESCS,
    228			    ENIC_MAX_WQ_DESCS);
    229		return -EINVAL;
    230	}
    231	if (running)
    232		dev_close(netdev);
    233	c->rq_desc_count =
    234		ring->rx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
    235	c->wq_desc_count =
    236		ring->tx_pending & 0xffffffe0; /* must be aligned to groups of 32 */
    237	enic_free_vnic_resources(enic);
    238	err = enic_alloc_vnic_resources(enic);
    239	if (err) {
    240		netdev_err(netdev,
    241			   "Failed to alloc vNIC resources, aborting\n");
    242		enic_free_vnic_resources(enic);
    243		goto err_out;
    244	}
    245	enic_init_vnic_resources(enic);
    246	if (running) {
    247		err = dev_open(netdev, NULL);
    248		if (err)
    249			goto err_out;
    250	}
    251	return 0;
    252err_out:
    253	c->rq_desc_count = rx_pending;
    254	c->wq_desc_count = tx_pending;
    255	return err;
    256}
    257
    258static int enic_get_sset_count(struct net_device *netdev, int sset)
    259{
    260	switch (sset) {
    261	case ETH_SS_STATS:
    262		return enic_n_tx_stats + enic_n_rx_stats + enic_n_gen_stats;
    263	default:
    264		return -EOPNOTSUPP;
    265	}
    266}
    267
    268static void enic_get_ethtool_stats(struct net_device *netdev,
    269	struct ethtool_stats *stats, u64 *data)
    270{
    271	struct enic *enic = netdev_priv(netdev);
    272	struct vnic_stats *vstats;
    273	unsigned int i;
    274	int err;
    275
    276	err = enic_dev_stats_dump(enic, &vstats);
    277	/* return only when dma_alloc_coherent fails in vnic_dev_stats_dump
    278	 * For other failures, like devcmd failure, we return previously
    279	 * recorded stats.
    280	 */
    281	if (err == -ENOMEM)
    282		return;
    283
    284	for (i = 0; i < enic_n_tx_stats; i++)
    285		*(data++) = ((u64 *)&vstats->tx)[enic_tx_stats[i].index];
    286	for (i = 0; i < enic_n_rx_stats; i++)
    287		*(data++) = ((u64 *)&vstats->rx)[enic_rx_stats[i].index];
    288	for (i = 0; i < enic_n_gen_stats; i++)
    289		*(data++) = ((u64 *)&enic->gen_stats)[enic_gen_stats[i].index];
    290}
    291
    292static u32 enic_get_msglevel(struct net_device *netdev)
    293{
    294	struct enic *enic = netdev_priv(netdev);
    295	return enic->msg_enable;
    296}
    297
    298static void enic_set_msglevel(struct net_device *netdev, u32 value)
    299{
    300	struct enic *enic = netdev_priv(netdev);
    301	enic->msg_enable = value;
    302}
    303
    304static int enic_get_coalesce(struct net_device *netdev,
    305			     struct ethtool_coalesce *ecmd,
    306			     struct kernel_ethtool_coalesce *kernel_coal,
    307			     struct netlink_ext_ack *extack)
    308{
    309	struct enic *enic = netdev_priv(netdev);
    310	struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
    311
    312	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX)
    313		ecmd->tx_coalesce_usecs = enic->tx_coalesce_usecs;
    314	ecmd->rx_coalesce_usecs = enic->rx_coalesce_usecs;
    315	if (rxcoal->use_adaptive_rx_coalesce)
    316		ecmd->use_adaptive_rx_coalesce = 1;
    317	ecmd->rx_coalesce_usecs_low = rxcoal->small_pkt_range_start;
    318	ecmd->rx_coalesce_usecs_high = rxcoal->range_end;
    319
    320	return 0;
    321}
    322
    323static int enic_coalesce_valid(struct enic *enic,
    324			       struct ethtool_coalesce *ec)
    325{
    326	u32 coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
    327	u32 rx_coalesce_usecs_high = min_t(u32, coalesce_usecs_max,
    328					   ec->rx_coalesce_usecs_high);
    329	u32 rx_coalesce_usecs_low = min_t(u32, coalesce_usecs_max,
    330					  ec->rx_coalesce_usecs_low);
    331
    332	if ((vnic_dev_get_intr_mode(enic->vdev) != VNIC_DEV_INTR_MODE_MSIX) &&
    333	    ec->tx_coalesce_usecs)
    334		return -EINVAL;
    335
    336	if ((ec->tx_coalesce_usecs > coalesce_usecs_max)	||
    337	    (ec->rx_coalesce_usecs > coalesce_usecs_max)	||
    338	    (ec->rx_coalesce_usecs_low > coalesce_usecs_max)	||
    339	    (ec->rx_coalesce_usecs_high > coalesce_usecs_max))
    340		netdev_info(enic->netdev, "ethtool_set_coalesce: adaptor supports max coalesce value of %d. Setting max value.\n",
    341			    coalesce_usecs_max);
    342
    343	if (ec->rx_coalesce_usecs_high &&
    344	    (rx_coalesce_usecs_high <
    345	     rx_coalesce_usecs_low + ENIC_AIC_LARGE_PKT_DIFF))
    346		return -EINVAL;
    347
    348	return 0;
    349}
    350
    351static int enic_set_coalesce(struct net_device *netdev,
    352			     struct ethtool_coalesce *ecmd,
    353			     struct kernel_ethtool_coalesce *kernel_coal,
    354			     struct netlink_ext_ack *extack)
    355{
    356	struct enic *enic = netdev_priv(netdev);
    357	u32 tx_coalesce_usecs;
    358	u32 rx_coalesce_usecs;
    359	u32 rx_coalesce_usecs_low;
    360	u32 rx_coalesce_usecs_high;
    361	u32 coalesce_usecs_max;
    362	unsigned int i, intr;
    363	int ret;
    364	struct enic_rx_coal *rxcoal = &enic->rx_coalesce_setting;
    365
    366	ret = enic_coalesce_valid(enic, ecmd);
    367	if (ret)
    368		return ret;
    369	coalesce_usecs_max = vnic_dev_get_intr_coal_timer_max(enic->vdev);
    370	tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs,
    371				  coalesce_usecs_max);
    372	rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs,
    373				  coalesce_usecs_max);
    374
    375	rx_coalesce_usecs_low = min_t(u32, ecmd->rx_coalesce_usecs_low,
    376				      coalesce_usecs_max);
    377	rx_coalesce_usecs_high = min_t(u32, ecmd->rx_coalesce_usecs_high,
    378				       coalesce_usecs_max);
    379
    380	if (vnic_dev_get_intr_mode(enic->vdev) == VNIC_DEV_INTR_MODE_MSIX) {
    381		for (i = 0; i < enic->wq_count; i++) {
    382			intr = enic_msix_wq_intr(enic, i);
    383			vnic_intr_coalescing_timer_set(&enic->intr[intr],
    384						       tx_coalesce_usecs);
    385		}
    386		enic->tx_coalesce_usecs = tx_coalesce_usecs;
    387	}
    388	rxcoal->use_adaptive_rx_coalesce = !!ecmd->use_adaptive_rx_coalesce;
    389	if (!rxcoal->use_adaptive_rx_coalesce)
    390		enic_intr_coal_set_rx(enic, rx_coalesce_usecs);
    391	if (ecmd->rx_coalesce_usecs_high) {
    392		rxcoal->range_end = rx_coalesce_usecs_high;
    393		rxcoal->small_pkt_range_start = rx_coalesce_usecs_low;
    394		rxcoal->large_pkt_range_start = rx_coalesce_usecs_low +
    395						ENIC_AIC_LARGE_PKT_DIFF;
    396	}
    397
    398	enic->rx_coalesce_usecs = rx_coalesce_usecs;
    399
    400	return 0;
    401}
    402
    403static int enic_grxclsrlall(struct enic *enic, struct ethtool_rxnfc *cmd,
    404			    u32 *rule_locs)
    405{
    406	int j, ret = 0, cnt = 0;
    407
    408	cmd->data = enic->rfs_h.max - enic->rfs_h.free;
    409	for (j = 0; j < (1 << ENIC_RFS_FLW_BITSHIFT); j++) {
    410		struct hlist_head *hhead;
    411		struct hlist_node *tmp;
    412		struct enic_rfs_fltr_node *n;
    413
    414		hhead = &enic->rfs_h.ht_head[j];
    415		hlist_for_each_entry_safe(n, tmp, hhead, node) {
    416			if (cnt == cmd->rule_cnt)
    417				return -EMSGSIZE;
    418			rule_locs[cnt] = n->fltr_id;
    419			cnt++;
    420		}
    421	}
    422	cmd->rule_cnt = cnt;
    423
    424	return ret;
    425}
    426
    427static int enic_grxclsrule(struct enic *enic, struct ethtool_rxnfc *cmd)
    428{
    429	struct ethtool_rx_flow_spec *fsp =
    430				(struct ethtool_rx_flow_spec *)&cmd->fs;
    431	struct enic_rfs_fltr_node *n;
    432
    433	n = htbl_fltr_search(enic, (u16)fsp->location);
    434	if (!n)
    435		return -EINVAL;
    436	switch (n->keys.basic.ip_proto) {
    437	case IPPROTO_TCP:
    438		fsp->flow_type = TCP_V4_FLOW;
    439		break;
    440	case IPPROTO_UDP:
    441		fsp->flow_type = UDP_V4_FLOW;
    442		break;
    443	default:
    444		return -EINVAL;
    445	}
    446
    447	fsp->h_u.tcp_ip4_spec.ip4src = flow_get_u32_src(&n->keys);
    448	fsp->m_u.tcp_ip4_spec.ip4src = (__u32)~0;
    449
    450	fsp->h_u.tcp_ip4_spec.ip4dst = flow_get_u32_dst(&n->keys);
    451	fsp->m_u.tcp_ip4_spec.ip4dst = (__u32)~0;
    452
    453	fsp->h_u.tcp_ip4_spec.psrc = n->keys.ports.src;
    454	fsp->m_u.tcp_ip4_spec.psrc = (__u16)~0;
    455
    456	fsp->h_u.tcp_ip4_spec.pdst = n->keys.ports.dst;
    457	fsp->m_u.tcp_ip4_spec.pdst = (__u16)~0;
    458
    459	fsp->ring_cookie = n->rq_id;
    460
    461	return 0;
    462}
    463
    464static int enic_get_rx_flow_hash(struct enic *enic, struct ethtool_rxnfc *cmd)
    465{
    466	u8 rss_hash_type = 0;
    467	cmd->data = 0;
    468
    469	spin_lock_bh(&enic->devcmd_lock);
    470	(void)vnic_dev_capable_rss_hash_type(enic->vdev, &rss_hash_type);
    471	spin_unlock_bh(&enic->devcmd_lock);
    472	switch (cmd->flow_type) {
    473	case TCP_V6_FLOW:
    474	case TCP_V4_FLOW:
    475		cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3 |
    476			     RXH_IP_SRC | RXH_IP_DST;
    477		break;
    478	case UDP_V6_FLOW:
    479		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
    480		if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV6)
    481			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
    482		break;
    483	case UDP_V4_FLOW:
    484		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
    485		if (rss_hash_type & NIC_CFG_RSS_HASH_TYPE_UDP_IPV4)
    486			cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
    487		break;
    488	case SCTP_V4_FLOW:
    489	case AH_ESP_V4_FLOW:
    490	case AH_V4_FLOW:
    491	case ESP_V4_FLOW:
    492	case SCTP_V6_FLOW:
    493	case AH_ESP_V6_FLOW:
    494	case AH_V6_FLOW:
    495	case ESP_V6_FLOW:
    496	case IPV4_FLOW:
    497	case IPV6_FLOW:
    498		cmd->data |= RXH_IP_SRC | RXH_IP_DST;
    499		break;
    500	default:
    501		return -EINVAL;
    502	}
    503
    504	return 0;
    505}
    506
    507static int enic_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
    508			  u32 *rule_locs)
    509{
    510	struct enic *enic = netdev_priv(dev);
    511	int ret = 0;
    512
    513	switch (cmd->cmd) {
    514	case ETHTOOL_GRXRINGS:
    515		cmd->data = enic->rq_count;
    516		break;
    517	case ETHTOOL_GRXCLSRLCNT:
    518		spin_lock_bh(&enic->rfs_h.lock);
    519		cmd->rule_cnt = enic->rfs_h.max - enic->rfs_h.free;
    520		cmd->data = enic->rfs_h.max;
    521		spin_unlock_bh(&enic->rfs_h.lock);
    522		break;
    523	case ETHTOOL_GRXCLSRLALL:
    524		spin_lock_bh(&enic->rfs_h.lock);
    525		ret = enic_grxclsrlall(enic, cmd, rule_locs);
    526		spin_unlock_bh(&enic->rfs_h.lock);
    527		break;
    528	case ETHTOOL_GRXCLSRULE:
    529		spin_lock_bh(&enic->rfs_h.lock);
    530		ret = enic_grxclsrule(enic, cmd);
    531		spin_unlock_bh(&enic->rfs_h.lock);
    532		break;
    533	case ETHTOOL_GRXFH:
    534		ret = enic_get_rx_flow_hash(enic, cmd);
    535		break;
    536	default:
    537		ret = -EOPNOTSUPP;
    538		break;
    539	}
    540
    541	return ret;
    542}
    543
    544static int enic_get_tunable(struct net_device *dev,
    545			    const struct ethtool_tunable *tuna, void *data)
    546{
    547	struct enic *enic = netdev_priv(dev);
    548	int ret = 0;
    549
    550	switch (tuna->id) {
    551	case ETHTOOL_RX_COPYBREAK:
    552		*(u32 *)data = enic->rx_copybreak;
    553		break;
    554	default:
    555		ret = -EINVAL;
    556		break;
    557	}
    558
    559	return ret;
    560}
    561
    562static int enic_set_tunable(struct net_device *dev,
    563			    const struct ethtool_tunable *tuna,
    564			    const void *data)
    565{
    566	struct enic *enic = netdev_priv(dev);
    567	int ret = 0;
    568
    569	switch (tuna->id) {
    570	case ETHTOOL_RX_COPYBREAK:
    571		enic->rx_copybreak = *(u32 *)data;
    572		break;
    573	default:
    574		ret = -EINVAL;
    575		break;
    576	}
    577
    578	return ret;
    579}
    580
    581static u32 enic_get_rxfh_key_size(struct net_device *netdev)
    582{
    583	return ENIC_RSS_LEN;
    584}
    585
    586static int enic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey,
    587			 u8 *hfunc)
    588{
    589	struct enic *enic = netdev_priv(netdev);
    590
    591	if (hkey)
    592		memcpy(hkey, enic->rss_key, ENIC_RSS_LEN);
    593
    594	if (hfunc)
    595		*hfunc = ETH_RSS_HASH_TOP;
    596
    597	return 0;
    598}
    599
    600static int enic_set_rxfh(struct net_device *netdev, const u32 *indir,
    601			 const u8 *hkey, const u8 hfunc)
    602{
    603	struct enic *enic = netdev_priv(netdev);
    604
    605	if ((hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) ||
    606	    indir)
    607		return -EINVAL;
    608
    609	if (hkey)
    610		memcpy(enic->rss_key, hkey, ENIC_RSS_LEN);
    611
    612	return __enic_set_rsskey(enic);
    613}
    614
    615static int enic_get_ts_info(struct net_device *netdev,
    616			    struct ethtool_ts_info *info)
    617{
    618	info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
    619				SOF_TIMESTAMPING_RX_SOFTWARE |
    620				SOF_TIMESTAMPING_SOFTWARE;
    621
    622	return 0;
    623}
    624
    625static const struct ethtool_ops enic_ethtool_ops = {
    626	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
    627				     ETHTOOL_COALESCE_USE_ADAPTIVE_RX |
    628				     ETHTOOL_COALESCE_RX_USECS_LOW |
    629				     ETHTOOL_COALESCE_RX_USECS_HIGH,
    630	.get_drvinfo = enic_get_drvinfo,
    631	.get_msglevel = enic_get_msglevel,
    632	.set_msglevel = enic_set_msglevel,
    633	.get_link = ethtool_op_get_link,
    634	.get_strings = enic_get_strings,
    635	.get_ringparam = enic_get_ringparam,
    636	.set_ringparam = enic_set_ringparam,
    637	.get_sset_count = enic_get_sset_count,
    638	.get_ethtool_stats = enic_get_ethtool_stats,
    639	.get_coalesce = enic_get_coalesce,
    640	.set_coalesce = enic_set_coalesce,
    641	.get_rxnfc = enic_get_rxnfc,
    642	.get_tunable = enic_get_tunable,
    643	.set_tunable = enic_set_tunable,
    644	.get_rxfh_key_size = enic_get_rxfh_key_size,
    645	.get_rxfh = enic_get_rxfh,
    646	.set_rxfh = enic_set_rxfh,
    647	.get_link_ksettings = enic_get_ksettings,
    648	.get_ts_info = enic_get_ts_info,
    649};
    650
    651void enic_set_ethtool_ops(struct net_device *netdev)
    652{
    653	netdev->ethtool_ops = &enic_ethtool_ops;
    654}