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

pch_gbe_ethtool.c (14760B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 1999 - 2010 Intel Corporation.
      4 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
      5 *
      6 * This code was derived from the Intel e1000e Linux driver.
      7 */
      8#include "pch_gbe.h"
      9#include "pch_gbe_phy.h"
     10
     11static const char pch_driver_version[] = "1.01";
     12
     13/*
     14 * pch_gbe_stats - Stats item information
     15 */
     16struct pch_gbe_stats {
     17	char string[ETH_GSTRING_LEN];
     18	size_t size;
     19	size_t offset;
     20};
     21
     22#define PCH_GBE_STAT(m)						\
     23{								\
     24	.string = #m,						\
     25	.size = sizeof_field(struct pch_gbe_hw_stats, m),	\
     26	.offset = offsetof(struct pch_gbe_hw_stats, m),		\
     27}
     28
     29/*
     30 * pch_gbe_gstrings_stats - ethtool information status name list
     31 */
     32static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
     33	PCH_GBE_STAT(rx_packets),
     34	PCH_GBE_STAT(tx_packets),
     35	PCH_GBE_STAT(rx_bytes),
     36	PCH_GBE_STAT(tx_bytes),
     37	PCH_GBE_STAT(rx_errors),
     38	PCH_GBE_STAT(tx_errors),
     39	PCH_GBE_STAT(rx_dropped),
     40	PCH_GBE_STAT(tx_dropped),
     41	PCH_GBE_STAT(multicast),
     42	PCH_GBE_STAT(collisions),
     43	PCH_GBE_STAT(rx_crc_errors),
     44	PCH_GBE_STAT(rx_frame_errors),
     45	PCH_GBE_STAT(rx_alloc_buff_failed),
     46	PCH_GBE_STAT(tx_length_errors),
     47	PCH_GBE_STAT(tx_aborted_errors),
     48	PCH_GBE_STAT(tx_carrier_errors),
     49	PCH_GBE_STAT(tx_timeout_count),
     50	PCH_GBE_STAT(tx_restart_count),
     51	PCH_GBE_STAT(intr_rx_dsc_empty_count),
     52	PCH_GBE_STAT(intr_rx_frame_err_count),
     53	PCH_GBE_STAT(intr_rx_fifo_err_count),
     54	PCH_GBE_STAT(intr_rx_dma_err_count),
     55	PCH_GBE_STAT(intr_tx_fifo_err_count),
     56	PCH_GBE_STAT(intr_tx_dma_err_count),
     57	PCH_GBE_STAT(intr_tcpip_err_count)
     58};
     59
     60#define PCH_GBE_QUEUE_STATS_LEN 0
     61#define PCH_GBE_GLOBAL_STATS_LEN	ARRAY_SIZE(pch_gbe_gstrings_stats)
     62#define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
     63
     64#define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
     65#define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
     66/**
     67 * pch_gbe_get_link_ksettings - Get device-specific settings
     68 * @netdev: Network interface device structure
     69 * @ecmd:   Ethtool command
     70 * Returns:
     71 *	0:			Successful.
     72 *	Negative value:		Failed.
     73 */
     74static int pch_gbe_get_link_ksettings(struct net_device *netdev,
     75				      struct ethtool_link_ksettings *ecmd)
     76{
     77	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
     78	u32 supported, advertising;
     79
     80	mii_ethtool_get_link_ksettings(&adapter->mii, ecmd);
     81
     82	ethtool_convert_link_mode_to_legacy_u32(&supported,
     83						ecmd->link_modes.supported);
     84	ethtool_convert_link_mode_to_legacy_u32(&advertising,
     85						ecmd->link_modes.advertising);
     86
     87	supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
     88	advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
     89
     90	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
     91						supported);
     92	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
     93						advertising);
     94
     95	if (!netif_carrier_ok(adapter->netdev))
     96		ecmd->base.speed = SPEED_UNKNOWN;
     97
     98	return 0;
     99}
    100
    101/**
    102 * pch_gbe_set_link_ksettings - Set device-specific settings
    103 * @netdev: Network interface device structure
    104 * @ecmd:   Ethtool command
    105 * Returns:
    106 *	0:			Successful.
    107 *	Negative value:		Failed.
    108 */
    109static int pch_gbe_set_link_ksettings(struct net_device *netdev,
    110				      const struct ethtool_link_ksettings *ecmd)
    111{
    112	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    113	struct pch_gbe_hw *hw = &adapter->hw;
    114	struct ethtool_link_ksettings copy_ecmd;
    115	u32 speed = ecmd->base.speed;
    116	u32 advertising;
    117	int ret;
    118
    119	pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
    120
    121	memcpy(&copy_ecmd, ecmd, sizeof(*ecmd));
    122
    123	/* when set_settings() is called with a ethtool_cmd previously
    124	 * filled by get_settings() on a down link, speed is -1: */
    125	if (speed == UINT_MAX) {
    126		speed = SPEED_1000;
    127		copy_ecmd.base.speed = speed;
    128		copy_ecmd.base.duplex = DUPLEX_FULL;
    129	}
    130	ret = mii_ethtool_set_link_ksettings(&adapter->mii, &copy_ecmd);
    131	if (ret) {
    132		netdev_err(netdev, "Error: mii_ethtool_set_link_ksettings\n");
    133		return ret;
    134	}
    135	hw->mac.link_speed = speed;
    136	hw->mac.link_duplex = copy_ecmd.base.duplex;
    137	ethtool_convert_link_mode_to_legacy_u32(
    138		&advertising, copy_ecmd.link_modes.advertising);
    139	hw->phy.autoneg_advertised = advertising;
    140	hw->mac.autoneg = copy_ecmd.base.autoneg;
    141
    142	/* reset the link */
    143	if (netif_running(adapter->netdev)) {
    144		pch_gbe_down(adapter);
    145		ret = pch_gbe_up(adapter);
    146	} else {
    147		pch_gbe_reset(adapter);
    148	}
    149	return ret;
    150}
    151
    152/**
    153 * pch_gbe_get_regs_len - Report the size of device registers
    154 * @netdev: Network interface device structure
    155 * Returns: the size of device registers.
    156 */
    157static int pch_gbe_get_regs_len(struct net_device *netdev)
    158{
    159	return PCH_GBE_REGS_LEN * (int)sizeof(u32);
    160}
    161
    162/**
    163 * pch_gbe_get_drvinfo - Report driver information
    164 * @netdev:  Network interface device structure
    165 * @drvinfo: Driver information structure
    166 */
    167static void pch_gbe_get_drvinfo(struct net_device *netdev,
    168				 struct ethtool_drvinfo *drvinfo)
    169{
    170	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    171
    172	strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
    173	strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
    174	strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
    175		sizeof(drvinfo->bus_info));
    176}
    177
    178/**
    179 * pch_gbe_get_regs - Get device registers
    180 * @netdev: Network interface device structure
    181 * @regs:   Ethtool register structure
    182 * @p:      Buffer pointer of read device register date
    183 */
    184static void pch_gbe_get_regs(struct net_device *netdev,
    185				struct ethtool_regs *regs, void *p)
    186{
    187	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    188	struct pch_gbe_hw *hw = &adapter->hw;
    189	struct pci_dev *pdev = adapter->pdev;
    190	u32 *regs_buff = p;
    191	u16 i, tmp;
    192
    193	regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
    194	for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
    195		*regs_buff++ = ioread32(&hw->reg->INT_ST + i);
    196	/* PHY register */
    197	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
    198		pch_gbe_phy_read_reg_miic(&adapter->hw, i, &tmp);
    199		*regs_buff++ = tmp;
    200	}
    201}
    202
    203/**
    204 * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
    205 * @netdev: Network interface device structure
    206 * @wol:    Wake-on-Lan information
    207 */
    208static void pch_gbe_get_wol(struct net_device *netdev,
    209				struct ethtool_wolinfo *wol)
    210{
    211	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    212
    213	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
    214	wol->wolopts = 0;
    215
    216	if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
    217		wol->wolopts |= WAKE_UCAST;
    218	if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
    219		wol->wolopts |= WAKE_MCAST;
    220	if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
    221		wol->wolopts |= WAKE_BCAST;
    222	if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
    223		wol->wolopts |= WAKE_MAGIC;
    224}
    225
    226/**
    227 * pch_gbe_set_wol - Turn Wake-on-Lan on or off
    228 * @netdev: Network interface device structure
    229 * @wol:    Pointer of wake-on-Lan information straucture
    230 * Returns:
    231 *	0:			Successful.
    232 *	Negative value:		Failed.
    233 */
    234static int pch_gbe_set_wol(struct net_device *netdev,
    235				struct ethtool_wolinfo *wol)
    236{
    237	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    238
    239	if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
    240		return -EOPNOTSUPP;
    241	/* these settings will always override what we currently have */
    242	adapter->wake_up_evt = 0;
    243
    244	if ((wol->wolopts & WAKE_UCAST))
    245		adapter->wake_up_evt |= PCH_GBE_WLC_IND;
    246	if ((wol->wolopts & WAKE_MCAST))
    247		adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
    248	if ((wol->wolopts & WAKE_BCAST))
    249		adapter->wake_up_evt |= PCH_GBE_WLC_BR;
    250	if ((wol->wolopts & WAKE_MAGIC))
    251		adapter->wake_up_evt |= PCH_GBE_WLC_MP;
    252	return 0;
    253}
    254
    255/**
    256 * pch_gbe_nway_reset - Restart autonegotiation
    257 * @netdev: Network interface device structure
    258 * Returns:
    259 *	0:			Successful.
    260 *	Negative value:		Failed.
    261 */
    262static int pch_gbe_nway_reset(struct net_device *netdev)
    263{
    264	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    265
    266	return mii_nway_restart(&adapter->mii);
    267}
    268
    269/**
    270 * pch_gbe_get_ringparam - Report ring sizes
    271 * @netdev:  Network interface device structure
    272 * @ring:    Ring param structure
    273 * @kernel_ring:	Ring external param structure
    274 * @extack:	netlink handle
    275 */
    276static void pch_gbe_get_ringparam(struct net_device *netdev,
    277				  struct ethtool_ringparam *ring,
    278				  struct kernel_ethtool_ringparam *kernel_ring,
    279				  struct netlink_ext_ack *extack)
    280{
    281	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    282	struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
    283	struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
    284
    285	ring->rx_max_pending = PCH_GBE_MAX_RXD;
    286	ring->tx_max_pending = PCH_GBE_MAX_TXD;
    287	ring->rx_pending = rxdr->count;
    288	ring->tx_pending = txdr->count;
    289}
    290
    291/**
    292 * pch_gbe_set_ringparam - Set ring sizes
    293 * @netdev:  Network interface device structure
    294 * @ring:    Ring param structure
    295 * @kernel_ring:	Ring external param structure
    296 * @extack:	netlink handle
    297 * Returns
    298 *	0:			Successful.
    299 *	Negative value:		Failed.
    300 */
    301static int pch_gbe_set_ringparam(struct net_device *netdev,
    302				 struct ethtool_ringparam *ring,
    303				 struct kernel_ethtool_ringparam *kernel_ring,
    304				 struct netlink_ext_ack *extack)
    305{
    306	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    307	struct pch_gbe_tx_ring *txdr, *tx_old;
    308	struct pch_gbe_rx_ring *rxdr, *rx_old;
    309	int tx_ring_size, rx_ring_size;
    310	int err = 0;
    311
    312	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
    313		return -EINVAL;
    314	tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
    315	rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
    316
    317	if ((netif_running(adapter->netdev)))
    318		pch_gbe_down(adapter);
    319	tx_old = adapter->tx_ring;
    320	rx_old = adapter->rx_ring;
    321
    322	txdr = kzalloc(tx_ring_size, GFP_KERNEL);
    323	if (!txdr) {
    324		err = -ENOMEM;
    325		goto err_alloc_tx;
    326	}
    327	rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
    328	if (!rxdr) {
    329		err = -ENOMEM;
    330		goto err_alloc_rx;
    331	}
    332	adapter->tx_ring = txdr;
    333	adapter->rx_ring = rxdr;
    334
    335	rxdr->count =
    336		clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
    337	rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
    338
    339	txdr->count =
    340		clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
    341	txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
    342
    343	if ((netif_running(adapter->netdev))) {
    344		/* Try to get new resources before deleting old */
    345		err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
    346		if (err)
    347			goto err_setup_rx;
    348		err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
    349		if (err)
    350			goto err_setup_tx;
    351		pch_gbe_free_rx_resources(adapter, rx_old);
    352		pch_gbe_free_tx_resources(adapter, tx_old);
    353		kfree(tx_old);
    354		kfree(rx_old);
    355		adapter->rx_ring = rxdr;
    356		adapter->tx_ring = txdr;
    357		err = pch_gbe_up(adapter);
    358	}
    359	return err;
    360
    361err_setup_tx:
    362	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
    363err_setup_rx:
    364	adapter->rx_ring = rx_old;
    365	adapter->tx_ring = tx_old;
    366	kfree(rxdr);
    367err_alloc_rx:
    368	kfree(txdr);
    369err_alloc_tx:
    370	if (netif_running(adapter->netdev))
    371		pch_gbe_up(adapter);
    372	return err;
    373}
    374
    375/**
    376 * pch_gbe_get_pauseparam - Report pause parameters
    377 * @netdev:  Network interface device structure
    378 * @pause:   Pause parameters structure
    379 */
    380static void pch_gbe_get_pauseparam(struct net_device *netdev,
    381				       struct ethtool_pauseparam *pause)
    382{
    383	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    384	struct pch_gbe_hw *hw = &adapter->hw;
    385
    386	pause->autoneg =
    387	    ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
    388
    389	if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
    390		pause->rx_pause = 1;
    391	} else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
    392		pause->tx_pause = 1;
    393	} else if (hw->mac.fc == PCH_GBE_FC_FULL) {
    394		pause->rx_pause = 1;
    395		pause->tx_pause = 1;
    396	}
    397}
    398
    399/**
    400 * pch_gbe_set_pauseparam - Set pause parameters
    401 * @netdev:  Network interface device structure
    402 * @pause:   Pause parameters structure
    403 * Returns:
    404 *	0:			Successful.
    405 *	Negative value:		Failed.
    406 */
    407static int pch_gbe_set_pauseparam(struct net_device *netdev,
    408				       struct ethtool_pauseparam *pause)
    409{
    410	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    411	struct pch_gbe_hw *hw = &adapter->hw;
    412	int ret = 0;
    413
    414	hw->mac.fc_autoneg = pause->autoneg;
    415	if ((pause->rx_pause) && (pause->tx_pause))
    416		hw->mac.fc = PCH_GBE_FC_FULL;
    417	else if ((pause->rx_pause) && (!pause->tx_pause))
    418		hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
    419	else if ((!pause->rx_pause) && (pause->tx_pause))
    420		hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
    421	else if ((!pause->rx_pause) && (!pause->tx_pause))
    422		hw->mac.fc = PCH_GBE_FC_NONE;
    423
    424	if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
    425		if ((netif_running(adapter->netdev))) {
    426			pch_gbe_down(adapter);
    427			ret = pch_gbe_up(adapter);
    428		} else {
    429			pch_gbe_reset(adapter);
    430		}
    431	} else {
    432		ret = pch_gbe_mac_force_mac_fc(hw);
    433	}
    434	return ret;
    435}
    436
    437/**
    438 * pch_gbe_get_strings - Return a set of strings that describe the requested
    439 *			 objects
    440 * @netdev:    Network interface device structure
    441 * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
    442 * @data:      Pointer of read string data.
    443 */
    444static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
    445					u8 *data)
    446{
    447	u8 *p = data;
    448	int i;
    449
    450	switch (stringset) {
    451	case (u32) ETH_SS_STATS:
    452		for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
    453			memcpy(p, pch_gbe_gstrings_stats[i].string,
    454			       ETH_GSTRING_LEN);
    455			p += ETH_GSTRING_LEN;
    456		}
    457		break;
    458	}
    459}
    460
    461/**
    462 * pch_gbe_get_ethtool_stats - Return statistics about the device
    463 * @netdev: Network interface device structure
    464 * @stats:  Ethtool statue structure
    465 * @data:   Pointer of read status area
    466 */
    467static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
    468				  struct ethtool_stats *stats, u64 *data)
    469{
    470	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
    471	int i;
    472	const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
    473	char *hw_stats = (char *)&adapter->stats;
    474
    475	pch_gbe_update_stats(adapter);
    476	for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
    477		char *p = hw_stats + gstats->offset;
    478		data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
    479		gstats++;
    480	}
    481}
    482
    483static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
    484{
    485	switch (sset) {
    486	case ETH_SS_STATS:
    487		return PCH_GBE_STATS_LEN;
    488	default:
    489		return -EOPNOTSUPP;
    490	}
    491}
    492
    493static const struct ethtool_ops pch_gbe_ethtool_ops = {
    494	.get_drvinfo = pch_gbe_get_drvinfo,
    495	.get_regs_len = pch_gbe_get_regs_len,
    496	.get_regs = pch_gbe_get_regs,
    497	.get_wol = pch_gbe_get_wol,
    498	.set_wol = pch_gbe_set_wol,
    499	.nway_reset = pch_gbe_nway_reset,
    500	.get_link = ethtool_op_get_link,
    501	.get_ringparam = pch_gbe_get_ringparam,
    502	.set_ringparam = pch_gbe_set_ringparam,
    503	.get_pauseparam = pch_gbe_get_pauseparam,
    504	.set_pauseparam = pch_gbe_set_pauseparam,
    505	.get_strings = pch_gbe_get_strings,
    506	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
    507	.get_sset_count = pch_gbe_get_sset_count,
    508	.get_link_ksettings = pch_gbe_get_link_ksettings,
    509	.set_link_ksettings = pch_gbe_set_link_ksettings,
    510};
    511
    512void pch_gbe_set_ethtool_ops(struct net_device *netdev)
    513{
    514	netdev->ethtool_ops = &pch_gbe_ethtool_ops;
    515}