12b72c9e3SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21c1538beSJeff Kirsher /*
31c1538beSJeff Kirsher  * Copyright (C) 1999 - 2010 Intel Corporation.
41c1538beSJeff Kirsher  * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
51c1538beSJeff Kirsher  *
61c1538beSJeff Kirsher  * This code was derived from the Intel e1000e Linux driver.
71c1538beSJeff Kirsher  */
81c1538beSJeff Kirsher #include "pch_gbe.h"
9c63ebdf0SPaul Burton #include "pch_gbe_phy.h"
101c1538beSJeff Kirsher 
1140b161bbSAndy Shevchenko static const char pch_driver_version[] = "1.01";
1240b161bbSAndy Shevchenko 
13d0ea5cbdSJesse Brandeburg /*
141c1538beSJeff Kirsher  * pch_gbe_stats - Stats item information
151c1538beSJeff Kirsher  */
161c1538beSJeff Kirsher struct pch_gbe_stats {
171c1538beSJeff Kirsher 	char string[ETH_GSTRING_LEN];
181c1538beSJeff Kirsher 	size_t size;
191c1538beSJeff Kirsher 	size_t offset;
201c1538beSJeff Kirsher };
211c1538beSJeff Kirsher 
221c1538beSJeff Kirsher #define PCH_GBE_STAT(m)						\
231c1538beSJeff Kirsher {								\
241c1538beSJeff Kirsher 	.string = #m,						\
25c593642cSPankaj Bharadiya 	.size = sizeof_field(struct pch_gbe_hw_stats, m),	\
261c1538beSJeff Kirsher 	.offset = offsetof(struct pch_gbe_hw_stats, m),		\
271c1538beSJeff Kirsher }
281c1538beSJeff Kirsher 
29d0ea5cbdSJesse Brandeburg /*
301c1538beSJeff Kirsher  * pch_gbe_gstrings_stats - ethtool information status name list
311c1538beSJeff Kirsher  */
321c1538beSJeff Kirsher static const struct pch_gbe_stats pch_gbe_gstrings_stats[] = {
331c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_packets),
341c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_packets),
351c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_bytes),
361c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_bytes),
371c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_errors),
381c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_errors),
391c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_dropped),
401c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_dropped),
411c1538beSJeff Kirsher 	PCH_GBE_STAT(multicast),
421c1538beSJeff Kirsher 	PCH_GBE_STAT(collisions),
431c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_crc_errors),
441c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_frame_errors),
451c1538beSJeff Kirsher 	PCH_GBE_STAT(rx_alloc_buff_failed),
461c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_length_errors),
471c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_aborted_errors),
481c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_carrier_errors),
491c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_timeout_count),
501c1538beSJeff Kirsher 	PCH_GBE_STAT(tx_restart_count),
511c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_rx_dsc_empty_count),
521c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_rx_frame_err_count),
531c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_rx_fifo_err_count),
541c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_rx_dma_err_count),
551c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_tx_fifo_err_count),
561c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_tx_dma_err_count),
571c1538beSJeff Kirsher 	PCH_GBE_STAT(intr_tcpip_err_count)
581c1538beSJeff Kirsher };
591c1538beSJeff Kirsher 
601c1538beSJeff Kirsher #define PCH_GBE_QUEUE_STATS_LEN 0
611c1538beSJeff Kirsher #define PCH_GBE_GLOBAL_STATS_LEN	ARRAY_SIZE(pch_gbe_gstrings_stats)
621c1538beSJeff Kirsher #define PCH_GBE_STATS_LEN (PCH_GBE_GLOBAL_STATS_LEN + PCH_GBE_QUEUE_STATS_LEN)
631c1538beSJeff Kirsher 
641c1538beSJeff Kirsher #define PCH_GBE_MAC_REGS_LEN    (sizeof(struct pch_gbe_regs) / 4)
651c1538beSJeff Kirsher #define PCH_GBE_REGS_LEN        (PCH_GBE_MAC_REGS_LEN + PCH_GBE_PHY_REGS_LEN)
661c1538beSJeff Kirsher /**
67ad8e963cSPhilippe Reynes  * pch_gbe_get_link_ksettings - Get device-specific settings
681c1538beSJeff Kirsher  * @netdev: Network interface device structure
691c1538beSJeff Kirsher  * @ecmd:   Ethtool command
7049ce9c2cSBen Hutchings  * Returns:
711c1538beSJeff Kirsher  *	0:			Successful.
721c1538beSJeff Kirsher  *	Negative value:		Failed.
731c1538beSJeff Kirsher  */
pch_gbe_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * ecmd)74ad8e963cSPhilippe Reynes static int pch_gbe_get_link_ksettings(struct net_device *netdev,
75ad8e963cSPhilippe Reynes 				      struct ethtool_link_ksettings *ecmd)
761c1538beSJeff Kirsher {
771c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
78ad8e963cSPhilippe Reynes 	u32 supported, advertising;
791c1538beSJeff Kirsher 
8082c01a84Syuval.shaia@oracle.com 	mii_ethtool_get_link_ksettings(&adapter->mii, ecmd);
81ad8e963cSPhilippe Reynes 
82ad8e963cSPhilippe Reynes 	ethtool_convert_link_mode_to_legacy_u32(&supported,
83ad8e963cSPhilippe Reynes 						ecmd->link_modes.supported);
84ad8e963cSPhilippe Reynes 	ethtool_convert_link_mode_to_legacy_u32(&advertising,
85ad8e963cSPhilippe Reynes 						ecmd->link_modes.advertising);
86ad8e963cSPhilippe Reynes 
87ad8e963cSPhilippe Reynes 	supported &= ~(SUPPORTED_TP | SUPPORTED_1000baseT_Half);
88ad8e963cSPhilippe Reynes 	advertising &= ~(ADVERTISED_TP | ADVERTISED_1000baseT_Half);
89ad8e963cSPhilippe Reynes 
90ad8e963cSPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.supported,
91ad8e963cSPhilippe Reynes 						supported);
92ad8e963cSPhilippe Reynes 	ethtool_convert_legacy_u32_to_link_mode(ecmd->link_modes.advertising,
93ad8e963cSPhilippe Reynes 						advertising);
941c1538beSJeff Kirsher 
951c1538beSJeff Kirsher 	if (!netif_carrier_ok(adapter->netdev))
96ad8e963cSPhilippe Reynes 		ecmd->base.speed = SPEED_UNKNOWN;
9782c01a84Syuval.shaia@oracle.com 
9882c01a84Syuval.shaia@oracle.com 	return 0;
991c1538beSJeff Kirsher }
1001c1538beSJeff Kirsher 
1011c1538beSJeff Kirsher /**
102ad8e963cSPhilippe Reynes  * pch_gbe_set_link_ksettings - Set device-specific settings
1031c1538beSJeff Kirsher  * @netdev: Network interface device structure
1041c1538beSJeff Kirsher  * @ecmd:   Ethtool command
10549ce9c2cSBen Hutchings  * Returns:
1061c1538beSJeff Kirsher  *	0:			Successful.
1071c1538beSJeff Kirsher  *	Negative value:		Failed.
1081c1538beSJeff Kirsher  */
pch_gbe_set_link_ksettings(struct net_device * netdev,const struct ethtool_link_ksettings * ecmd)109ad8e963cSPhilippe Reynes static int pch_gbe_set_link_ksettings(struct net_device *netdev,
110ad8e963cSPhilippe Reynes 				      const struct ethtool_link_ksettings *ecmd)
1111c1538beSJeff Kirsher {
1121c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
1131c1538beSJeff Kirsher 	struct pch_gbe_hw *hw = &adapter->hw;
114ad8e963cSPhilippe Reynes 	struct ethtool_link_ksettings copy_ecmd;
115ad8e963cSPhilippe Reynes 	u32 speed = ecmd->base.speed;
116ad8e963cSPhilippe Reynes 	u32 advertising;
1171c1538beSJeff Kirsher 	int ret;
1181c1538beSJeff Kirsher 
119c96a0f74SPaul Burton 	pch_gbe_phy_write_reg_miic(hw, MII_BMCR, BMCR_RESET);
1201c1538beSJeff Kirsher 
121ad8e963cSPhilippe Reynes 	memcpy(&copy_ecmd, ecmd, sizeof(*ecmd));
122ad8e963cSPhilippe Reynes 
1231c1538beSJeff Kirsher 	/* when set_settings() is called with a ethtool_cmd previously
1241c1538beSJeff Kirsher 	 * filled by get_settings() on a down link, speed is -1: */
1251c1538beSJeff Kirsher 	if (speed == UINT_MAX) {
1261c1538beSJeff Kirsher 		speed = SPEED_1000;
127ad8e963cSPhilippe Reynes 		copy_ecmd.base.speed = speed;
128ad8e963cSPhilippe Reynes 		copy_ecmd.base.duplex = DUPLEX_FULL;
1291c1538beSJeff Kirsher 	}
130ad8e963cSPhilippe Reynes 	ret = mii_ethtool_set_link_ksettings(&adapter->mii, &copy_ecmd);
1311c1538beSJeff Kirsher 	if (ret) {
132ad8e963cSPhilippe Reynes 		netdev_err(netdev, "Error: mii_ethtool_set_link_ksettings\n");
1331c1538beSJeff Kirsher 		return ret;
1341c1538beSJeff Kirsher 	}
1351c1538beSJeff Kirsher 	hw->mac.link_speed = speed;
136ad8e963cSPhilippe Reynes 	hw->mac.link_duplex = copy_ecmd.base.duplex;
137ad8e963cSPhilippe Reynes 	ethtool_convert_link_mode_to_legacy_u32(
138ad8e963cSPhilippe Reynes 		&advertising, copy_ecmd.link_modes.advertising);
139ad8e963cSPhilippe Reynes 	hw->phy.autoneg_advertised = advertising;
140ad8e963cSPhilippe Reynes 	hw->mac.autoneg = copy_ecmd.base.autoneg;
1411c1538beSJeff Kirsher 
1421c1538beSJeff Kirsher 	/* reset the link */
1431c1538beSJeff Kirsher 	if (netif_running(adapter->netdev)) {
1441c1538beSJeff Kirsher 		pch_gbe_down(adapter);
1451c1538beSJeff Kirsher 		ret = pch_gbe_up(adapter);
1461c1538beSJeff Kirsher 	} else {
1471c1538beSJeff Kirsher 		pch_gbe_reset(adapter);
1481c1538beSJeff Kirsher 	}
1491c1538beSJeff Kirsher 	return ret;
1501c1538beSJeff Kirsher }
1511c1538beSJeff Kirsher 
1521c1538beSJeff Kirsher /**
1531c1538beSJeff Kirsher  * pch_gbe_get_regs_len - Report the size of device registers
1541c1538beSJeff Kirsher  * @netdev: Network interface device structure
1551c1538beSJeff Kirsher  * Returns: the size of device registers.
1561c1538beSJeff Kirsher  */
pch_gbe_get_regs_len(struct net_device * netdev)1571c1538beSJeff Kirsher static int pch_gbe_get_regs_len(struct net_device *netdev)
1581c1538beSJeff Kirsher {
1591c1538beSJeff Kirsher 	return PCH_GBE_REGS_LEN * (int)sizeof(u32);
1601c1538beSJeff Kirsher }
1611c1538beSJeff Kirsher 
1621c1538beSJeff Kirsher /**
1631c1538beSJeff Kirsher  * pch_gbe_get_drvinfo - Report driver information
1641c1538beSJeff Kirsher  * @netdev:  Network interface device structure
1651c1538beSJeff Kirsher  * @drvinfo: Driver information structure
1661c1538beSJeff Kirsher  */
pch_gbe_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * drvinfo)1671c1538beSJeff Kirsher static void pch_gbe_get_drvinfo(struct net_device *netdev,
1681c1538beSJeff Kirsher 				 struct ethtool_drvinfo *drvinfo)
1691c1538beSJeff Kirsher {
1701c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
1711c1538beSJeff Kirsher 
172*f029c781SWolfram Sang 	strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
173*f029c781SWolfram Sang 	strscpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
174*f029c781SWolfram Sang 	strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
17523020ab3SRick Jones 		sizeof(drvinfo->bus_info));
1761c1538beSJeff Kirsher }
1771c1538beSJeff Kirsher 
1781c1538beSJeff Kirsher /**
1791c1538beSJeff Kirsher  * pch_gbe_get_regs - Get device registers
1801c1538beSJeff Kirsher  * @netdev: Network interface device structure
1811c1538beSJeff Kirsher  * @regs:   Ethtool register structure
1821c1538beSJeff Kirsher  * @p:      Buffer pointer of read device register date
1831c1538beSJeff Kirsher  */
pch_gbe_get_regs(struct net_device * netdev,struct ethtool_regs * regs,void * p)1841c1538beSJeff Kirsher static void pch_gbe_get_regs(struct net_device *netdev,
1851c1538beSJeff Kirsher 				struct ethtool_regs *regs, void *p)
1861c1538beSJeff Kirsher {
1871c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
1881c1538beSJeff Kirsher 	struct pch_gbe_hw *hw = &adapter->hw;
1891c1538beSJeff Kirsher 	struct pci_dev *pdev = adapter->pdev;
1901c1538beSJeff Kirsher 	u32 *regs_buff = p;
1911c1538beSJeff Kirsher 	u16 i, tmp;
1921c1538beSJeff Kirsher 
1931c1538beSJeff Kirsher 	regs->version = 0x1000000 | (__u32)pdev->revision << 16 | pdev->device;
1941c1538beSJeff Kirsher 	for (i = 0; i < PCH_GBE_MAC_REGS_LEN; i++)
1951c1538beSJeff Kirsher 		*regs_buff++ = ioread32(&hw->reg->INT_ST + i);
1961c1538beSJeff Kirsher 	/* PHY register */
1971c1538beSJeff Kirsher 	for (i = 0; i < PCH_GBE_PHY_REGS_LEN; i++) {
198c96a0f74SPaul Burton 		pch_gbe_phy_read_reg_miic(&adapter->hw, i, &tmp);
1991c1538beSJeff Kirsher 		*regs_buff++ = tmp;
2001c1538beSJeff Kirsher 	}
2011c1538beSJeff Kirsher }
2021c1538beSJeff Kirsher 
2031c1538beSJeff Kirsher /**
2041c1538beSJeff Kirsher  * pch_gbe_get_wol - Report whether Wake-on-Lan is enabled
2051c1538beSJeff Kirsher  * @netdev: Network interface device structure
2061c1538beSJeff Kirsher  * @wol:    Wake-on-Lan information
2071c1538beSJeff Kirsher  */
pch_gbe_get_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)2081c1538beSJeff Kirsher static void pch_gbe_get_wol(struct net_device *netdev,
2091c1538beSJeff Kirsher 				struct ethtool_wolinfo *wol)
2101c1538beSJeff Kirsher {
2111c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
2121c1538beSJeff Kirsher 
2131c1538beSJeff Kirsher 	wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC;
2141c1538beSJeff Kirsher 	wol->wolopts = 0;
2151c1538beSJeff Kirsher 
2161c1538beSJeff Kirsher 	if ((adapter->wake_up_evt & PCH_GBE_WLC_IND))
2171c1538beSJeff Kirsher 		wol->wolopts |= WAKE_UCAST;
2181c1538beSJeff Kirsher 	if ((adapter->wake_up_evt & PCH_GBE_WLC_MLT))
2191c1538beSJeff Kirsher 		wol->wolopts |= WAKE_MCAST;
2201c1538beSJeff Kirsher 	if ((adapter->wake_up_evt & PCH_GBE_WLC_BR))
2211c1538beSJeff Kirsher 		wol->wolopts |= WAKE_BCAST;
2221c1538beSJeff Kirsher 	if ((adapter->wake_up_evt & PCH_GBE_WLC_MP))
2231c1538beSJeff Kirsher 		wol->wolopts |= WAKE_MAGIC;
2241c1538beSJeff Kirsher }
2251c1538beSJeff Kirsher 
2261c1538beSJeff Kirsher /**
2271c1538beSJeff Kirsher  * pch_gbe_set_wol - Turn Wake-on-Lan on or off
2281c1538beSJeff Kirsher  * @netdev: Network interface device structure
2291c1538beSJeff Kirsher  * @wol:    Pointer of wake-on-Lan information straucture
23049ce9c2cSBen Hutchings  * Returns:
2311c1538beSJeff Kirsher  *	0:			Successful.
2321c1538beSJeff Kirsher  *	Negative value:		Failed.
2331c1538beSJeff Kirsher  */
pch_gbe_set_wol(struct net_device * netdev,struct ethtool_wolinfo * wol)2341c1538beSJeff Kirsher static int pch_gbe_set_wol(struct net_device *netdev,
2351c1538beSJeff Kirsher 				struct ethtool_wolinfo *wol)
2361c1538beSJeff Kirsher {
2371c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
2381c1538beSJeff Kirsher 
2391c1538beSJeff Kirsher 	if ((wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)))
2401c1538beSJeff Kirsher 		return -EOPNOTSUPP;
2411c1538beSJeff Kirsher 	/* these settings will always override what we currently have */
2421c1538beSJeff Kirsher 	adapter->wake_up_evt = 0;
2431c1538beSJeff Kirsher 
2441c1538beSJeff Kirsher 	if ((wol->wolopts & WAKE_UCAST))
2451c1538beSJeff Kirsher 		adapter->wake_up_evt |= PCH_GBE_WLC_IND;
2461c1538beSJeff Kirsher 	if ((wol->wolopts & WAKE_MCAST))
2471c1538beSJeff Kirsher 		adapter->wake_up_evt |= PCH_GBE_WLC_MLT;
2481c1538beSJeff Kirsher 	if ((wol->wolopts & WAKE_BCAST))
2491c1538beSJeff Kirsher 		adapter->wake_up_evt |= PCH_GBE_WLC_BR;
2501c1538beSJeff Kirsher 	if ((wol->wolopts & WAKE_MAGIC))
2511c1538beSJeff Kirsher 		adapter->wake_up_evt |= PCH_GBE_WLC_MP;
2521c1538beSJeff Kirsher 	return 0;
2531c1538beSJeff Kirsher }
2541c1538beSJeff Kirsher 
2551c1538beSJeff Kirsher /**
2561c1538beSJeff Kirsher  * pch_gbe_nway_reset - Restart autonegotiation
2571c1538beSJeff Kirsher  * @netdev: Network interface device structure
25849ce9c2cSBen Hutchings  * Returns:
2591c1538beSJeff Kirsher  *	0:			Successful.
2601c1538beSJeff Kirsher  *	Negative value:		Failed.
2611c1538beSJeff Kirsher  */
pch_gbe_nway_reset(struct net_device * netdev)2621c1538beSJeff Kirsher static int pch_gbe_nway_reset(struct net_device *netdev)
2631c1538beSJeff Kirsher {
2641c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
2651c1538beSJeff Kirsher 
2661c1538beSJeff Kirsher 	return mii_nway_restart(&adapter->mii);
2671c1538beSJeff Kirsher }
2681c1538beSJeff Kirsher 
2691c1538beSJeff Kirsher /**
2701c1538beSJeff Kirsher  * pch_gbe_get_ringparam - Report ring sizes
2711c1538beSJeff Kirsher  * @netdev:  Network interface device structure
2721c1538beSJeff Kirsher  * @ring:    Ring param structure
27374624944SHao Chen  * @kernel_ring:	Ring external param structure
27474624944SHao Chen  * @extack:	netlink handle
2751c1538beSJeff Kirsher  */
pch_gbe_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)2761c1538beSJeff Kirsher static void pch_gbe_get_ringparam(struct net_device *netdev,
27774624944SHao Chen 				  struct ethtool_ringparam *ring,
27874624944SHao Chen 				  struct kernel_ethtool_ringparam *kernel_ring,
27974624944SHao Chen 				  struct netlink_ext_ack *extack)
2801c1538beSJeff Kirsher {
2811c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
2821c1538beSJeff Kirsher 	struct pch_gbe_tx_ring *txdr = adapter->tx_ring;
2831c1538beSJeff Kirsher 	struct pch_gbe_rx_ring *rxdr = adapter->rx_ring;
2841c1538beSJeff Kirsher 
2851c1538beSJeff Kirsher 	ring->rx_max_pending = PCH_GBE_MAX_RXD;
2861c1538beSJeff Kirsher 	ring->tx_max_pending = PCH_GBE_MAX_TXD;
2871c1538beSJeff Kirsher 	ring->rx_pending = rxdr->count;
2881c1538beSJeff Kirsher 	ring->tx_pending = txdr->count;
2891c1538beSJeff Kirsher }
2901c1538beSJeff Kirsher 
2911c1538beSJeff Kirsher /**
2921c1538beSJeff Kirsher  * pch_gbe_set_ringparam - Set ring sizes
2931c1538beSJeff Kirsher  * @netdev:  Network interface device structure
2941c1538beSJeff Kirsher  * @ring:    Ring param structure
29574624944SHao Chen  * @kernel_ring:	Ring external param structure
29674624944SHao Chen  * @extack:	netlink handle
2971c1538beSJeff Kirsher  * Returns
2981c1538beSJeff Kirsher  *	0:			Successful.
2991c1538beSJeff Kirsher  *	Negative value:		Failed.
3001c1538beSJeff Kirsher  */
pch_gbe_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)3011c1538beSJeff Kirsher static int pch_gbe_set_ringparam(struct net_device *netdev,
30274624944SHao Chen 				 struct ethtool_ringparam *ring,
30374624944SHao Chen 				 struct kernel_ethtool_ringparam *kernel_ring,
30474624944SHao Chen 				 struct netlink_ext_ack *extack)
3051c1538beSJeff Kirsher {
3061c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
3071c1538beSJeff Kirsher 	struct pch_gbe_tx_ring *txdr, *tx_old;
3081c1538beSJeff Kirsher 	struct pch_gbe_rx_ring *rxdr, *rx_old;
3091c1538beSJeff Kirsher 	int tx_ring_size, rx_ring_size;
3101c1538beSJeff Kirsher 	int err = 0;
3111c1538beSJeff Kirsher 
3121c1538beSJeff Kirsher 	if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
3131c1538beSJeff Kirsher 		return -EINVAL;
3141c1538beSJeff Kirsher 	tx_ring_size = (int)sizeof(struct pch_gbe_tx_ring);
3151c1538beSJeff Kirsher 	rx_ring_size = (int)sizeof(struct pch_gbe_rx_ring);
3161c1538beSJeff Kirsher 
3171c1538beSJeff Kirsher 	if ((netif_running(adapter->netdev)))
3181c1538beSJeff Kirsher 		pch_gbe_down(adapter);
3191c1538beSJeff Kirsher 	tx_old = adapter->tx_ring;
3201c1538beSJeff Kirsher 	rx_old = adapter->rx_ring;
3211c1538beSJeff Kirsher 
3221c1538beSJeff Kirsher 	txdr = kzalloc(tx_ring_size, GFP_KERNEL);
3231c1538beSJeff Kirsher 	if (!txdr) {
3241c1538beSJeff Kirsher 		err = -ENOMEM;
3251c1538beSJeff Kirsher 		goto err_alloc_tx;
3261c1538beSJeff Kirsher 	}
3271c1538beSJeff Kirsher 	rxdr = kzalloc(rx_ring_size, GFP_KERNEL);
3281c1538beSJeff Kirsher 	if (!rxdr) {
3291c1538beSJeff Kirsher 		err = -ENOMEM;
3301c1538beSJeff Kirsher 		goto err_alloc_rx;
3311c1538beSJeff Kirsher 	}
3321c1538beSJeff Kirsher 	adapter->tx_ring = txdr;
3331c1538beSJeff Kirsher 	adapter->rx_ring = rxdr;
3341c1538beSJeff Kirsher 
3351c1538beSJeff Kirsher 	rxdr->count =
3361c1538beSJeff Kirsher 		clamp_val(ring->rx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
3371c1538beSJeff Kirsher 	rxdr->count = roundup(rxdr->count, PCH_GBE_RX_DESC_MULTIPLE);
3381c1538beSJeff Kirsher 
3391c1538beSJeff Kirsher 	txdr->count =
3401c1538beSJeff Kirsher 		clamp_val(ring->tx_pending, PCH_GBE_MIN_RXD, PCH_GBE_MAX_RXD);
3411c1538beSJeff Kirsher 	txdr->count = roundup(txdr->count, PCH_GBE_TX_DESC_MULTIPLE);
3421c1538beSJeff Kirsher 
3431c1538beSJeff Kirsher 	if ((netif_running(adapter->netdev))) {
3441c1538beSJeff Kirsher 		/* Try to get new resources before deleting old */
3451c1538beSJeff Kirsher 		err = pch_gbe_setup_rx_resources(adapter, adapter->rx_ring);
3461c1538beSJeff Kirsher 		if (err)
3471c1538beSJeff Kirsher 			goto err_setup_rx;
3481c1538beSJeff Kirsher 		err = pch_gbe_setup_tx_resources(adapter, adapter->tx_ring);
3491c1538beSJeff Kirsher 		if (err)
3501c1538beSJeff Kirsher 			goto err_setup_tx;
3511c1538beSJeff Kirsher 		pch_gbe_free_rx_resources(adapter, rx_old);
3521c1538beSJeff Kirsher 		pch_gbe_free_tx_resources(adapter, tx_old);
3531c1538beSJeff Kirsher 		kfree(tx_old);
3541c1538beSJeff Kirsher 		kfree(rx_old);
3551c1538beSJeff Kirsher 		adapter->rx_ring = rxdr;
3561c1538beSJeff Kirsher 		adapter->tx_ring = txdr;
3571c1538beSJeff Kirsher 		err = pch_gbe_up(adapter);
3581c1538beSJeff Kirsher 	}
3591c1538beSJeff Kirsher 	return err;
3601c1538beSJeff Kirsher 
3611c1538beSJeff Kirsher err_setup_tx:
3621c1538beSJeff Kirsher 	pch_gbe_free_rx_resources(adapter, adapter->rx_ring);
3631c1538beSJeff Kirsher err_setup_rx:
3641c1538beSJeff Kirsher 	adapter->rx_ring = rx_old;
3651c1538beSJeff Kirsher 	adapter->tx_ring = tx_old;
3661c1538beSJeff Kirsher 	kfree(rxdr);
3671c1538beSJeff Kirsher err_alloc_rx:
3681c1538beSJeff Kirsher 	kfree(txdr);
3691c1538beSJeff Kirsher err_alloc_tx:
3701c1538beSJeff Kirsher 	if (netif_running(adapter->netdev))
3711c1538beSJeff Kirsher 		pch_gbe_up(adapter);
3721c1538beSJeff Kirsher 	return err;
3731c1538beSJeff Kirsher }
3741c1538beSJeff Kirsher 
3751c1538beSJeff Kirsher /**
3761c1538beSJeff Kirsher  * pch_gbe_get_pauseparam - Report pause parameters
3771c1538beSJeff Kirsher  * @netdev:  Network interface device structure
3781c1538beSJeff Kirsher  * @pause:   Pause parameters structure
3791c1538beSJeff Kirsher  */
pch_gbe_get_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)3801c1538beSJeff Kirsher static void pch_gbe_get_pauseparam(struct net_device *netdev,
3811c1538beSJeff Kirsher 				       struct ethtool_pauseparam *pause)
3821c1538beSJeff Kirsher {
3831c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
3841c1538beSJeff Kirsher 	struct pch_gbe_hw *hw = &adapter->hw;
3851c1538beSJeff Kirsher 
3861c1538beSJeff Kirsher 	pause->autoneg =
3871c1538beSJeff Kirsher 	    ((hw->mac.fc_autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
3881c1538beSJeff Kirsher 
3891c1538beSJeff Kirsher 	if (hw->mac.fc == PCH_GBE_FC_RX_PAUSE) {
3901c1538beSJeff Kirsher 		pause->rx_pause = 1;
3911c1538beSJeff Kirsher 	} else if (hw->mac.fc == PCH_GBE_FC_TX_PAUSE) {
3921c1538beSJeff Kirsher 		pause->tx_pause = 1;
3931c1538beSJeff Kirsher 	} else if (hw->mac.fc == PCH_GBE_FC_FULL) {
3941c1538beSJeff Kirsher 		pause->rx_pause = 1;
3951c1538beSJeff Kirsher 		pause->tx_pause = 1;
3961c1538beSJeff Kirsher 	}
3971c1538beSJeff Kirsher }
3981c1538beSJeff Kirsher 
3991c1538beSJeff Kirsher /**
400dbedd44eSJoe Perches  * pch_gbe_set_pauseparam - Set pause parameters
4011c1538beSJeff Kirsher  * @netdev:  Network interface device structure
4021c1538beSJeff Kirsher  * @pause:   Pause parameters structure
40349ce9c2cSBen Hutchings  * Returns:
4041c1538beSJeff Kirsher  *	0:			Successful.
4051c1538beSJeff Kirsher  *	Negative value:		Failed.
4061c1538beSJeff Kirsher  */
pch_gbe_set_pauseparam(struct net_device * netdev,struct ethtool_pauseparam * pause)4071c1538beSJeff Kirsher static int pch_gbe_set_pauseparam(struct net_device *netdev,
4081c1538beSJeff Kirsher 				       struct ethtool_pauseparam *pause)
4091c1538beSJeff Kirsher {
4101c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
4111c1538beSJeff Kirsher 	struct pch_gbe_hw *hw = &adapter->hw;
4121c1538beSJeff Kirsher 	int ret = 0;
4131c1538beSJeff Kirsher 
4141c1538beSJeff Kirsher 	hw->mac.fc_autoneg = pause->autoneg;
4151c1538beSJeff Kirsher 	if ((pause->rx_pause) && (pause->tx_pause))
4161c1538beSJeff Kirsher 		hw->mac.fc = PCH_GBE_FC_FULL;
4171c1538beSJeff Kirsher 	else if ((pause->rx_pause) && (!pause->tx_pause))
4181c1538beSJeff Kirsher 		hw->mac.fc = PCH_GBE_FC_RX_PAUSE;
4191c1538beSJeff Kirsher 	else if ((!pause->rx_pause) && (pause->tx_pause))
4201c1538beSJeff Kirsher 		hw->mac.fc = PCH_GBE_FC_TX_PAUSE;
4211c1538beSJeff Kirsher 	else if ((!pause->rx_pause) && (!pause->tx_pause))
4221c1538beSJeff Kirsher 		hw->mac.fc = PCH_GBE_FC_NONE;
4231c1538beSJeff Kirsher 
4241c1538beSJeff Kirsher 	if (hw->mac.fc_autoneg == AUTONEG_ENABLE) {
4251c1538beSJeff Kirsher 		if ((netif_running(adapter->netdev))) {
4261c1538beSJeff Kirsher 			pch_gbe_down(adapter);
4271c1538beSJeff Kirsher 			ret = pch_gbe_up(adapter);
4281c1538beSJeff Kirsher 		} else {
4291c1538beSJeff Kirsher 			pch_gbe_reset(adapter);
4301c1538beSJeff Kirsher 		}
4311c1538beSJeff Kirsher 	} else {
4321c1538beSJeff Kirsher 		ret = pch_gbe_mac_force_mac_fc(hw);
4331c1538beSJeff Kirsher 	}
4341c1538beSJeff Kirsher 	return ret;
4351c1538beSJeff Kirsher }
4361c1538beSJeff Kirsher 
4371c1538beSJeff Kirsher /**
4381c1538beSJeff Kirsher  * pch_gbe_get_strings - Return a set of strings that describe the requested
4391c1538beSJeff Kirsher  *			 objects
4401c1538beSJeff Kirsher  * @netdev:    Network interface device structure
4411c1538beSJeff Kirsher  * @stringset: Select the stringset. [ETH_SS_TEST] [ETH_SS_STATS]
4421c1538beSJeff Kirsher  * @data:      Pointer of read string data.
4431c1538beSJeff Kirsher  */
pch_gbe_get_strings(struct net_device * netdev,u32 stringset,u8 * data)4441c1538beSJeff Kirsher static void pch_gbe_get_strings(struct net_device *netdev, u32 stringset,
4451c1538beSJeff Kirsher 					u8 *data)
4461c1538beSJeff Kirsher {
4471c1538beSJeff Kirsher 	u8 *p = data;
4481c1538beSJeff Kirsher 	int i;
4491c1538beSJeff Kirsher 
4501c1538beSJeff Kirsher 	switch (stringset) {
4511c1538beSJeff Kirsher 	case (u32) ETH_SS_STATS:
4521c1538beSJeff Kirsher 		for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
4531c1538beSJeff Kirsher 			memcpy(p, pch_gbe_gstrings_stats[i].string,
4541c1538beSJeff Kirsher 			       ETH_GSTRING_LEN);
4551c1538beSJeff Kirsher 			p += ETH_GSTRING_LEN;
4561c1538beSJeff Kirsher 		}
4571c1538beSJeff Kirsher 		break;
4581c1538beSJeff Kirsher 	}
4591c1538beSJeff Kirsher }
4601c1538beSJeff Kirsher 
4611c1538beSJeff Kirsher /**
4621c1538beSJeff Kirsher  * pch_gbe_get_ethtool_stats - Return statistics about the device
4631c1538beSJeff Kirsher  * @netdev: Network interface device structure
4641c1538beSJeff Kirsher  * @stats:  Ethtool statue structure
4651c1538beSJeff Kirsher  * @data:   Pointer of read status area
4661c1538beSJeff Kirsher  */
pch_gbe_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)4671c1538beSJeff Kirsher static void pch_gbe_get_ethtool_stats(struct net_device *netdev,
4681c1538beSJeff Kirsher 				  struct ethtool_stats *stats, u64 *data)
4691c1538beSJeff Kirsher {
4701c1538beSJeff Kirsher 	struct pch_gbe_adapter *adapter = netdev_priv(netdev);
4711c1538beSJeff Kirsher 	int i;
4721c1538beSJeff Kirsher 	const struct pch_gbe_stats *gstats = pch_gbe_gstrings_stats;
4731c1538beSJeff Kirsher 	char *hw_stats = (char *)&adapter->stats;
4741c1538beSJeff Kirsher 
4751c1538beSJeff Kirsher 	pch_gbe_update_stats(adapter);
4761c1538beSJeff Kirsher 	for (i = 0; i < PCH_GBE_GLOBAL_STATS_LEN; i++) {
4771c1538beSJeff Kirsher 		char *p = hw_stats + gstats->offset;
4781c1538beSJeff Kirsher 		data[i] = gstats->size == sizeof(u64) ? *(u64 *)p:(*(u32 *)p);
4791c1538beSJeff Kirsher 		gstats++;
4801c1538beSJeff Kirsher 	}
4811c1538beSJeff Kirsher }
4821c1538beSJeff Kirsher 
pch_gbe_get_sset_count(struct net_device * netdev,int sset)4831c1538beSJeff Kirsher static int pch_gbe_get_sset_count(struct net_device *netdev, int sset)
4841c1538beSJeff Kirsher {
4851c1538beSJeff Kirsher 	switch (sset) {
4861c1538beSJeff Kirsher 	case ETH_SS_STATS:
4871c1538beSJeff Kirsher 		return PCH_GBE_STATS_LEN;
4881c1538beSJeff Kirsher 	default:
4891c1538beSJeff Kirsher 		return -EOPNOTSUPP;
4901c1538beSJeff Kirsher 	}
4911c1538beSJeff Kirsher }
4921c1538beSJeff Kirsher 
4931c1538beSJeff Kirsher static const struct ethtool_ops pch_gbe_ethtool_ops = {
4941c1538beSJeff Kirsher 	.get_drvinfo = pch_gbe_get_drvinfo,
4951c1538beSJeff Kirsher 	.get_regs_len = pch_gbe_get_regs_len,
4961c1538beSJeff Kirsher 	.get_regs = pch_gbe_get_regs,
4971c1538beSJeff Kirsher 	.get_wol = pch_gbe_get_wol,
4981c1538beSJeff Kirsher 	.set_wol = pch_gbe_set_wol,
4991c1538beSJeff Kirsher 	.nway_reset = pch_gbe_nway_reset,
5001c1538beSJeff Kirsher 	.get_link = ethtool_op_get_link,
5011c1538beSJeff Kirsher 	.get_ringparam = pch_gbe_get_ringparam,
5021c1538beSJeff Kirsher 	.set_ringparam = pch_gbe_set_ringparam,
5031c1538beSJeff Kirsher 	.get_pauseparam = pch_gbe_get_pauseparam,
5041c1538beSJeff Kirsher 	.set_pauseparam = pch_gbe_set_pauseparam,
5051c1538beSJeff Kirsher 	.get_strings = pch_gbe_get_strings,
5061c1538beSJeff Kirsher 	.get_ethtool_stats = pch_gbe_get_ethtool_stats,
5071c1538beSJeff Kirsher 	.get_sset_count = pch_gbe_get_sset_count,
508ad8e963cSPhilippe Reynes 	.get_link_ksettings = pch_gbe_get_link_ksettings,
509ad8e963cSPhilippe Reynes 	.set_link_ksettings = pch_gbe_set_link_ksettings,
5101c1538beSJeff Kirsher };
5111c1538beSJeff Kirsher 
pch_gbe_set_ethtool_ops(struct net_device * netdev)5121c1538beSJeff Kirsher void pch_gbe_set_ethtool_ops(struct net_device *netdev)
5131c1538beSJeff Kirsher {
5147ad24ea4SWilfried Klaebe 	netdev->ethtool_ops = &pch_gbe_ethtool_ops;
5151c1538beSJeff Kirsher }
516