diff options
Diffstat (limited to 'drivers/net/ethernet/atheros')
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/alx.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/ethtool.c | 101 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/hw.c | 58 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/hw.h | 71 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/main.c | 84 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/alx/reg.h | 52 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c.h | 7 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_hw.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1c/atl1c_main.c | 73 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1e/atl1e.h | 13 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c | 6 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 94 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl1.c | 65 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl1.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl2.c | 14 | ||||
| -rw-r--r-- | drivers/net/ethernet/atheros/atlx/atl2.h | 2 | 
17 files changed, 512 insertions, 140 deletions
diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h index d71103dbf2c..8fc93c5f6ab 100644 --- a/drivers/net/ethernet/atheros/alx/alx.h +++ b/drivers/net/ethernet/atheros/alx/alx.h @@ -106,6 +106,9 @@ struct alx_priv {  	u16 msg_enable;  	bool msi; + +	/* protects hw.stats */ +	spinlock_t stats_lock;  };  extern const struct ethtool_ops alx_ethtool_ops; diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 45b36507abc..08e22df2a30 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -46,6 +46,66 @@  #include "reg.h"  #include "hw.h" +/* The order of these strings must match the order of the fields in + * struct alx_hw_stats + * See hw.h + */ +static const char alx_gstrings_stats[][ETH_GSTRING_LEN] = { +	"rx_packets", +	"rx_bcast_packets", +	"rx_mcast_packets", +	"rx_pause_packets", +	"rx_ctrl_packets", +	"rx_fcs_errors", +	"rx_length_errors", +	"rx_bytes", +	"rx_runt_packets", +	"rx_fragments", +	"rx_64B_or_less_packets", +	"rx_65B_to_127B_packets", +	"rx_128B_to_255B_packets", +	"rx_256B_to_511B_packets", +	"rx_512B_to_1023B_packets", +	"rx_1024B_to_1518B_packets", +	"rx_1519B_to_mtu_packets", +	"rx_oversize_packets", +	"rx_rxf_ov_drop_packets", +	"rx_rrd_ov_drop_packets", +	"rx_align_errors", +	"rx_bcast_bytes", +	"rx_mcast_bytes", +	"rx_address_errors", +	"tx_packets", +	"tx_bcast_packets", +	"tx_mcast_packets", +	"tx_pause_packets", +	"tx_exc_defer_packets", +	"tx_ctrl_packets", +	"tx_defer_packets", +	"tx_bytes", +	"tx_64B_or_less_packets", +	"tx_65B_to_127B_packets", +	"tx_128B_to_255B_packets", +	"tx_256B_to_511B_packets", +	"tx_512B_to_1023B_packets", +	"tx_1024B_to_1518B_packets", +	"tx_1519B_to_mtu_packets", +	"tx_single_collision", +	"tx_multiple_collisions", +	"tx_late_collision", +	"tx_abort_collision", +	"tx_underrun", +	"tx_trd_eop", +	"tx_length_errors", +	"tx_trunc_packets", +	"tx_bcast_bytes", +	"tx_mcast_bytes", +	"tx_update", +}; + +#define ALX_NUM_STATS ARRAY_SIZE(alx_gstrings_stats) + +  static u32 alx_get_supported_speeds(struct alx_hw *hw)  {  	u32 supported = SUPPORTED_10baseT_Half | @@ -201,6 +261,44 @@ static void alx_set_msglevel(struct net_device *netdev, u32 data)  	alx->msg_enable = data;  } +static void alx_get_ethtool_stats(struct net_device *netdev, +				  struct ethtool_stats *estats, u64 *data) +{ +	struct alx_priv *alx = netdev_priv(netdev); +	struct alx_hw *hw = &alx->hw; + +	spin_lock(&alx->stats_lock); + +	alx_update_hw_stats(hw); +	BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) < +		     ALX_NUM_STATS * sizeof(u64)); +	memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64)); + +	spin_unlock(&alx->stats_lock); +} + +static void alx_get_strings(struct net_device *netdev, u32 stringset, u8 *buf) +{ +	switch (stringset) { +	case ETH_SS_STATS: +		memcpy(buf, &alx_gstrings_stats, sizeof(alx_gstrings_stats)); +		break; +	default: +		WARN_ON(1); +		break; +	} +} + +static int alx_get_sset_count(struct net_device *netdev, int sset) +{ +	switch (sset) { +	case ETH_SS_STATS: +		return ALX_NUM_STATS; +	default: +		return -EINVAL; +	} +} +  const struct ethtool_ops alx_ethtool_ops = {  	.get_settings	= alx_get_settings,  	.set_settings	= alx_set_settings, @@ -209,4 +307,7 @@ const struct ethtool_ops alx_ethtool_ops = {  	.get_msglevel	= alx_get_msglevel,  	.set_msglevel	= alx_set_msglevel,  	.get_link	= ethtool_op_get_link, +	.get_strings	= alx_get_strings, +	.get_sset_count	= alx_get_sset_count, +	.get_ethtool_stats	= alx_get_ethtool_stats,  }; diff --git a/drivers/net/ethernet/atheros/alx/hw.c b/drivers/net/ethernet/atheros/alx/hw.c index 1e8c24a3cb4..7712f068f6d 100644 --- a/drivers/net/ethernet/atheros/alx/hw.c +++ b/drivers/net/ethernet/atheros/alx/hw.c @@ -1050,3 +1050,61 @@ bool alx_get_phy_info(struct alx_hw *hw)  	return true;  } + +void alx_update_hw_stats(struct alx_hw *hw) +{ +	/* RX stats */ +	hw->stats.rx_ok          += alx_read_mem32(hw, ALX_MIB_RX_OK); +	hw->stats.rx_bcast       += alx_read_mem32(hw, ALX_MIB_RX_BCAST); +	hw->stats.rx_mcast       += alx_read_mem32(hw, ALX_MIB_RX_MCAST); +	hw->stats.rx_pause       += alx_read_mem32(hw, ALX_MIB_RX_PAUSE); +	hw->stats.rx_ctrl        += alx_read_mem32(hw, ALX_MIB_RX_CTRL); +	hw->stats.rx_fcs_err     += alx_read_mem32(hw, ALX_MIB_RX_FCS_ERR); +	hw->stats.rx_len_err     += alx_read_mem32(hw, ALX_MIB_RX_LEN_ERR); +	hw->stats.rx_byte_cnt    += alx_read_mem32(hw, ALX_MIB_RX_BYTE_CNT); +	hw->stats.rx_runt        += alx_read_mem32(hw, ALX_MIB_RX_RUNT); +	hw->stats.rx_frag        += alx_read_mem32(hw, ALX_MIB_RX_FRAG); +	hw->stats.rx_sz_64B      += alx_read_mem32(hw, ALX_MIB_RX_SZ_64B); +	hw->stats.rx_sz_127B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_127B); +	hw->stats.rx_sz_255B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_255B); +	hw->stats.rx_sz_511B     += alx_read_mem32(hw, ALX_MIB_RX_SZ_511B); +	hw->stats.rx_sz_1023B    += alx_read_mem32(hw, ALX_MIB_RX_SZ_1023B); +	hw->stats.rx_sz_1518B    += alx_read_mem32(hw, ALX_MIB_RX_SZ_1518B); +	hw->stats.rx_sz_max      += alx_read_mem32(hw, ALX_MIB_RX_SZ_MAX); +	hw->stats.rx_ov_sz       += alx_read_mem32(hw, ALX_MIB_RX_OV_SZ); +	hw->stats.rx_ov_rxf      += alx_read_mem32(hw, ALX_MIB_RX_OV_RXF); +	hw->stats.rx_ov_rrd      += alx_read_mem32(hw, ALX_MIB_RX_OV_RRD); +	hw->stats.rx_align_err   += alx_read_mem32(hw, ALX_MIB_RX_ALIGN_ERR); +	hw->stats.rx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_BCCNT); +	hw->stats.rx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_MCCNT); +	hw->stats.rx_err_addr    += alx_read_mem32(hw, ALX_MIB_RX_ERRADDR); + +	/* TX stats */ +	hw->stats.tx_ok          += alx_read_mem32(hw, ALX_MIB_TX_OK); +	hw->stats.tx_bcast       += alx_read_mem32(hw, ALX_MIB_TX_BCAST); +	hw->stats.tx_mcast       += alx_read_mem32(hw, ALX_MIB_TX_MCAST); +	hw->stats.tx_pause       += alx_read_mem32(hw, ALX_MIB_TX_PAUSE); +	hw->stats.tx_exc_defer   += alx_read_mem32(hw, ALX_MIB_TX_EXC_DEFER); +	hw->stats.tx_ctrl        += alx_read_mem32(hw, ALX_MIB_TX_CTRL); +	hw->stats.tx_defer       += alx_read_mem32(hw, ALX_MIB_TX_DEFER); +	hw->stats.tx_byte_cnt    += alx_read_mem32(hw, ALX_MIB_TX_BYTE_CNT); +	hw->stats.tx_sz_64B      += alx_read_mem32(hw, ALX_MIB_TX_SZ_64B); +	hw->stats.tx_sz_127B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_127B); +	hw->stats.tx_sz_255B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_255B); +	hw->stats.tx_sz_511B     += alx_read_mem32(hw, ALX_MIB_TX_SZ_511B); +	hw->stats.tx_sz_1023B    += alx_read_mem32(hw, ALX_MIB_TX_SZ_1023B); +	hw->stats.tx_sz_1518B    += alx_read_mem32(hw, ALX_MIB_TX_SZ_1518B); +	hw->stats.tx_sz_max      += alx_read_mem32(hw, ALX_MIB_TX_SZ_MAX); +	hw->stats.tx_single_col  += alx_read_mem32(hw, ALX_MIB_TX_SINGLE_COL); +	hw->stats.tx_multi_col   += alx_read_mem32(hw, ALX_MIB_TX_MULTI_COL); +	hw->stats.tx_late_col    += alx_read_mem32(hw, ALX_MIB_TX_LATE_COL); +	hw->stats.tx_abort_col   += alx_read_mem32(hw, ALX_MIB_TX_ABORT_COL); +	hw->stats.tx_underrun    += alx_read_mem32(hw, ALX_MIB_TX_UNDERRUN); +	hw->stats.tx_trd_eop     += alx_read_mem32(hw, ALX_MIB_TX_TRD_EOP); +	hw->stats.tx_len_err     += alx_read_mem32(hw, ALX_MIB_TX_LEN_ERR); +	hw->stats.tx_trunc       += alx_read_mem32(hw, ALX_MIB_TX_TRUNC); +	hw->stats.tx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_BCCNT); +	hw->stats.tx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_MCCNT); + +	hw->stats.update         += alx_read_mem32(hw, ALX_MIB_UPDATE); +} diff --git a/drivers/net/ethernet/atheros/alx/hw.h b/drivers/net/ethernet/atheros/alx/hw.h index 96f3b4381e1..15548802d6f 100644 --- a/drivers/net/ethernet/atheros/alx/hw.h +++ b/drivers/net/ethernet/atheros/alx/hw.h @@ -381,6 +381,73 @@ struct alx_rrd {  				 ALX_ISR_RX_Q6 | \  				 ALX_ISR_RX_Q7) +/* Statistics counters collected by the MAC + * + * The order of the fields must match the strings in alx_gstrings_stats + * All stats fields should be u64 + * See ethtool.c + */ +struct alx_hw_stats { +	/* rx */ +	u64 rx_ok;		/* good RX packets */ +	u64 rx_bcast;		/* good RX broadcast packets */ +	u64 rx_mcast;		/* good RX multicast packets */ +	u64 rx_pause;		/* RX pause frames */ +	u64 rx_ctrl;		/* RX control packets other than pause frames */ +	u64 rx_fcs_err;		/* RX packets with bad FCS */ +	u64 rx_len_err;		/* RX packets with length != actual size */ +	u64 rx_byte_cnt;	/* good bytes received. FCS is NOT included */ +	u64 rx_runt;		/* RX packets < 64 bytes with good FCS */ +	u64 rx_frag;		/* RX packets < 64 bytes with bad FCS */ +	u64 rx_sz_64B;		/* 64 byte RX packets */ +	u64 rx_sz_127B;		/* 65-127 byte RX packets */ +	u64 rx_sz_255B;		/* 128-255 byte RX packets */ +	u64 rx_sz_511B;		/* 256-511 byte RX packets */ +	u64 rx_sz_1023B;	/* 512-1023 byte RX packets */ +	u64 rx_sz_1518B;	/* 1024-1518 byte RX packets */ +	u64 rx_sz_max;		/* 1519 byte to MTU RX packets */ +	u64 rx_ov_sz;		/* truncated RX packets, size > MTU */ +	u64 rx_ov_rxf;		/* frames dropped due to RX FIFO overflow */ +	u64 rx_ov_rrd;		/* frames dropped due to RRD overflow */ +	u64 rx_align_err;	/* alignment errors */ +	u64 rx_bc_byte_cnt;	/* RX broadcast bytes, excluding FCS */ +	u64 rx_mc_byte_cnt;	/* RX multicast bytes, excluding FCS */ +	u64 rx_err_addr;	/* packets dropped due to address filtering */ + +	/* tx */ +	u64 tx_ok;		/* good TX packets */ +	u64 tx_bcast;		/* good TX broadcast packets */ +	u64 tx_mcast;		/* good TX multicast packets */ +	u64 tx_pause;		/* TX pause frames */ +	u64 tx_exc_defer;	/* TX packets deferred excessively */ +	u64 tx_ctrl;		/* TX control frames, excluding pause frames */ +	u64 tx_defer;		/* TX packets deferred */ +	u64 tx_byte_cnt;	/* bytes transmitted, FCS is NOT included */ +	u64 tx_sz_64B;		/* 64 byte TX packets */ +	u64 tx_sz_127B;		/* 65-127 byte TX packets */ +	u64 tx_sz_255B;		/* 128-255 byte TX packets */ +	u64 tx_sz_511B;		/* 256-511 byte TX packets */ +	u64 tx_sz_1023B;	/* 512-1023 byte TX packets */ +	u64 tx_sz_1518B;	/* 1024-1518 byte TX packets */ +	u64 tx_sz_max;		/* 1519 byte to MTU TX packets */ +	u64 tx_single_col;	/* packets TX after a single collision */ +	u64 tx_multi_col;	/* packets TX after multiple collisions */ +	u64 tx_late_col;	/* TX packets with late collisions */ +	u64 tx_abort_col;	/* TX packets aborted w/excessive collisions */ +	u64 tx_underrun;	/* TX packets aborted due to TX FIFO underrun +				 * or TRD FIFO underrun +				 */ +	u64 tx_trd_eop;		/* reads beyond the EOP into the next frame +				 * when TRD was not written timely +				 */ +	u64 tx_len_err;		/* TX packets where length != actual size */ +	u64 tx_trunc;		/* TX packets truncated due to size > MTU */ +	u64 tx_bc_byte_cnt;	/* broadcast bytes transmitted, excluding FCS */ +	u64 tx_mc_byte_cnt;	/* multicast bytes transmitted, excluding FCS */ +	u64 update; +}; + +  /* maximum interrupt vectors for msix */  #define ALX_MAX_MSIX_INTRS	16 @@ -424,6 +491,9 @@ struct alx_hw {  	/* PHY link patch flag */  	bool lnk_patch; + +	/* cumulated stats from the hardware (registers are cleared on read) */ +	struct alx_hw_stats stats;  };  static inline int alx_hw_revision(struct alx_hw *hw) @@ -491,6 +561,7 @@ bool alx_phy_configured(struct alx_hw *hw);  void alx_configure_basic(struct alx_hw *hw);  void alx_disable_rss(struct alx_hw *hw);  bool alx_get_phy_info(struct alx_hw *hw); +void alx_update_hw_stats(struct alx_hw *hw);  static inline u32 alx_speed_to_ethadv(int speed, u8 duplex)  { diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 027398ebbba..49faa97a30c 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -535,7 +535,7 @@ static int alx_alloc_descriptors(struct alx_priv *alx)  	if (!alx->descmem.virt)  		goto out_free; -	alx->txq.tpd = (void *)alx->descmem.virt; +	alx->txq.tpd = alx->descmem.virt;  	alx->txq.tpd_dma = alx->descmem.dma;  	/* alignment requirement for next block */ @@ -1097,7 +1097,7 @@ static netdev_tx_t alx_start_xmit(struct sk_buff *skb,  	return NETDEV_TX_OK;  drop: -	dev_kfree_skb(skb); +	dev_kfree_skb_any(skb);  	return NETDEV_TX_OK;  } @@ -1166,10 +1166,60 @@ static void alx_poll_controller(struct net_device *netdev)  }  #endif +static struct rtnl_link_stats64 *alx_get_stats64(struct net_device *dev, +					struct rtnl_link_stats64 *net_stats) +{ +	struct alx_priv *alx = netdev_priv(dev); +	struct alx_hw_stats *hw_stats = &alx->hw.stats; + +	spin_lock(&alx->stats_lock); + +	alx_update_hw_stats(&alx->hw); + +	net_stats->tx_bytes   = hw_stats->tx_byte_cnt; +	net_stats->rx_bytes   = hw_stats->rx_byte_cnt; +	net_stats->multicast  = hw_stats->rx_mcast; +	net_stats->collisions = hw_stats->tx_single_col + +				hw_stats->tx_multi_col + +				hw_stats->tx_late_col + +				hw_stats->tx_abort_col; + +	net_stats->rx_errors  = hw_stats->rx_frag + +				hw_stats->rx_fcs_err + +				hw_stats->rx_len_err + +				hw_stats->rx_ov_sz + +				hw_stats->rx_ov_rrd + +				hw_stats->rx_align_err + +				hw_stats->rx_ov_rxf; + +	net_stats->rx_fifo_errors   = hw_stats->rx_ov_rxf; +	net_stats->rx_length_errors = hw_stats->rx_len_err; +	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err; +	net_stats->rx_frame_errors  = hw_stats->rx_align_err; +	net_stats->rx_dropped       = hw_stats->rx_ov_rrd; + +	net_stats->tx_errors = hw_stats->tx_late_col + +			       hw_stats->tx_abort_col + +			       hw_stats->tx_underrun + +			       hw_stats->tx_trunc; + +	net_stats->tx_aborted_errors = hw_stats->tx_abort_col; +	net_stats->tx_fifo_errors    = hw_stats->tx_underrun; +	net_stats->tx_window_errors  = hw_stats->tx_late_col; + +	net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors; +	net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors; + +	spin_unlock(&alx->stats_lock); + +	return net_stats; +} +  static const struct net_device_ops alx_netdev_ops = {  	.ndo_open               = alx_open,  	.ndo_stop               = alx_stop,  	.ndo_start_xmit         = alx_start_xmit, +	.ndo_get_stats64        = alx_get_stats64,  	.ndo_set_rx_mode        = alx_set_rx_mode,  	.ndo_validate_addr      = eth_validate_addr,  	.ndo_set_mac_address    = alx_set_mac_address, @@ -1188,7 +1238,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	struct alx_priv *alx;  	struct alx_hw *hw;  	bool phy_configured; -	int bars, pm_cap, err; +	int bars, err;  	err = pci_enable_device_mem(pdev);  	if (err) @@ -1198,19 +1248,13 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	 * shared register for the high 32 bits, so only a single, aligned,  	 * 4 GB physical address range can be used for descriptors.  	 */ -	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) && -	    !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) { +	if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) {  		dev_dbg(&pdev->dev, "DMA to 64-BIT addresses\n");  	} else { -		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); +		err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));  		if (err) { -			err = dma_set_coherent_mask(&pdev->dev, -						    DMA_BIT_MASK(32)); -			if (err) { -				dev_err(&pdev->dev, -					"No usable DMA config, aborting\n"); -				goto out_pci_disable; -			} +			dev_err(&pdev->dev, "No usable DMA config, aborting\n"); +			goto out_pci_disable;  		}  	} @@ -1225,18 +1269,13 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	pci_enable_pcie_error_reporting(pdev);  	pci_set_master(pdev); -	pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); -	if (pm_cap == 0) { +	if (!pdev->pm_cap) {  		dev_err(&pdev->dev,  			"Can't find power management capability, aborting\n");  		err = -EIO;  		goto out_pci_release;  	} -	err = pci_set_power_state(pdev, PCI_D0); -	if (err) -		goto out_pci_release; -  	netdev = alloc_etherdev(sizeof(*alx));  	if (!netdev) {  		err = -ENOMEM; @@ -1247,6 +1286,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	alx = netdev_priv(netdev);  	spin_lock_init(&alx->hw.mdio_lock);  	spin_lock_init(&alx->irq_lock); +	spin_lock_init(&alx->stats_lock);  	alx->dev = netdev;  	alx->hw.pdev = pdev;  	alx->msg_enable = NETIF_MSG_LINK | NETIF_MSG_HW | NETIF_MSG_IFUP | @@ -1262,7 +1302,7 @@ static int alx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	}  	netdev->netdev_ops = &alx_netdev_ops; -	SET_ETHTOOL_OPS(netdev, &alx_ethtool_ops); +	netdev->ethtool_ops = &alx_ethtool_ops;  	netdev->irq = pdev->irq;  	netdev->watchdog_timeo = ALX_WATCHDOG_TIME; @@ -1372,7 +1412,6 @@ static void alx_remove(struct pci_dev *pdev)  	pci_disable_pcie_error_reporting(pdev);  	pci_disable_device(pdev); -	pci_set_drvdata(pdev, NULL);  	free_netdev(alx->dev);  } @@ -1394,6 +1433,9 @@ static int alx_resume(struct device *dev)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	struct alx_priv *alx = pci_get_drvdata(pdev); +	struct alx_hw *hw = &alx->hw; + +	alx_reset_phy(hw);  	if (!netif_running(alx->dev))  		return 0; diff --git a/drivers/net/ethernet/atheros/alx/reg.h b/drivers/net/ethernet/atheros/alx/reg.h index e4358c98bc4..af006b44b2a 100644 --- a/drivers/net/ethernet/atheros/alx/reg.h +++ b/drivers/net/ethernet/atheros/alx/reg.h @@ -404,15 +404,59 @@  /* MIB */  #define ALX_MIB_BASE					0x1700 +  #define ALX_MIB_RX_OK					(ALX_MIB_BASE + 0) +#define ALX_MIB_RX_BCAST				(ALX_MIB_BASE + 4) +#define ALX_MIB_RX_MCAST				(ALX_MIB_BASE + 8) +#define ALX_MIB_RX_PAUSE				(ALX_MIB_BASE + 12) +#define ALX_MIB_RX_CTRL					(ALX_MIB_BASE + 16) +#define ALX_MIB_RX_FCS_ERR				(ALX_MIB_BASE + 20) +#define ALX_MIB_RX_LEN_ERR				(ALX_MIB_BASE + 24) +#define ALX_MIB_RX_BYTE_CNT				(ALX_MIB_BASE + 28) +#define ALX_MIB_RX_RUNT					(ALX_MIB_BASE + 32) +#define ALX_MIB_RX_FRAG					(ALX_MIB_BASE + 36) +#define ALX_MIB_RX_SZ_64B				(ALX_MIB_BASE + 40) +#define ALX_MIB_RX_SZ_127B				(ALX_MIB_BASE + 44) +#define ALX_MIB_RX_SZ_255B				(ALX_MIB_BASE + 48) +#define ALX_MIB_RX_SZ_511B				(ALX_MIB_BASE + 52) +#define ALX_MIB_RX_SZ_1023B				(ALX_MIB_BASE + 56) +#define ALX_MIB_RX_SZ_1518B				(ALX_MIB_BASE + 60) +#define ALX_MIB_RX_SZ_MAX				(ALX_MIB_BASE + 64) +#define ALX_MIB_RX_OV_SZ				(ALX_MIB_BASE + 68) +#define ALX_MIB_RX_OV_RXF				(ALX_MIB_BASE + 72) +#define ALX_MIB_RX_OV_RRD				(ALX_MIB_BASE + 76) +#define ALX_MIB_RX_ALIGN_ERR				(ALX_MIB_BASE + 80) +#define ALX_MIB_RX_BCCNT				(ALX_MIB_BASE + 84) +#define ALX_MIB_RX_MCCNT				(ALX_MIB_BASE + 88)  #define ALX_MIB_RX_ERRADDR				(ALX_MIB_BASE + 92) +  #define ALX_MIB_TX_OK					(ALX_MIB_BASE + 96) +#define ALX_MIB_TX_BCAST				(ALX_MIB_BASE + 100) +#define ALX_MIB_TX_MCAST				(ALX_MIB_BASE + 104) +#define ALX_MIB_TX_PAUSE				(ALX_MIB_BASE + 108) +#define ALX_MIB_TX_EXC_DEFER				(ALX_MIB_BASE + 112) +#define ALX_MIB_TX_CTRL					(ALX_MIB_BASE + 116) +#define ALX_MIB_TX_DEFER				(ALX_MIB_BASE + 120) +#define ALX_MIB_TX_BYTE_CNT				(ALX_MIB_BASE + 124) +#define ALX_MIB_TX_SZ_64B				(ALX_MIB_BASE + 128) +#define ALX_MIB_TX_SZ_127B				(ALX_MIB_BASE + 132) +#define ALX_MIB_TX_SZ_255B				(ALX_MIB_BASE + 136) +#define ALX_MIB_TX_SZ_511B				(ALX_MIB_BASE + 140) +#define ALX_MIB_TX_SZ_1023B				(ALX_MIB_BASE + 144) +#define ALX_MIB_TX_SZ_1518B				(ALX_MIB_BASE + 148) +#define ALX_MIB_TX_SZ_MAX				(ALX_MIB_BASE + 152) +#define ALX_MIB_TX_SINGLE_COL				(ALX_MIB_BASE + 156) +#define ALX_MIB_TX_MULTI_COL				(ALX_MIB_BASE + 160) +#define ALX_MIB_TX_LATE_COL				(ALX_MIB_BASE + 164) +#define ALX_MIB_TX_ABORT_COL				(ALX_MIB_BASE + 168) +#define ALX_MIB_TX_UNDERRUN				(ALX_MIB_BASE + 172) +#define ALX_MIB_TX_TRD_EOP				(ALX_MIB_BASE + 176) +#define ALX_MIB_TX_LEN_ERR				(ALX_MIB_BASE + 180) +#define ALX_MIB_TX_TRUNC				(ALX_MIB_BASE + 184) +#define ALX_MIB_TX_BCCNT				(ALX_MIB_BASE + 188)  #define ALX_MIB_TX_MCCNT				(ALX_MIB_BASE + 192) +#define ALX_MIB_UPDATE					(ALX_MIB_BASE + 196) -#define ALX_RX_STATS_BIN				ALX_MIB_RX_OK -#define ALX_RX_STATS_END				ALX_MIB_RX_ERRADDR -#define ALX_TX_STATS_BIN				ALX_MIB_TX_OK -#define ALX_TX_STATS_END				ALX_MIB_TX_MCCNT  #define ALX_ISR						0x1600  #define ALX_ISR_DIS					BIT(31) diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c.h b/drivers/net/ethernet/atheros/atl1c/atl1c.h index 0f0556526ba..b9203d92893 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c.h +++ b/drivers/net/ethernet/atheros/atl1c/atl1c.h @@ -22,7 +22,6 @@  #ifndef _ATL1C_H_  #define _ATL1C_H_ -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/types.h>  #include <linux/errno.h> @@ -600,7 +599,7 @@ struct atl1c_adapter {  extern char atl1c_driver_name[];  extern char atl1c_driver_version[]; -extern void atl1c_reinit_locked(struct atl1c_adapter *adapter); -extern s32 atl1c_reset_hw(struct atl1c_hw *hw); -extern void atl1c_set_ethtool_ops(struct net_device *netdev); +void atl1c_reinit_locked(struct atl1c_adapter *adapter); +s32 atl1c_reset_hw(struct atl1c_hw *hw); +void atl1c_set_ethtool_ops(struct net_device *netdev);  #endif /* _ATL1C_H_ */ diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c index 859ea844ba0..48694c239d5 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c @@ -56,8 +56,8 @@ static int atl1c_get_settings(struct net_device *netdev,  		else  			ecmd->duplex = DUPLEX_HALF;  	} else { -		ethtool_cmd_speed_set(ecmd, -1); -		ecmd->duplex = -1; +		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); +		ecmd->duplex = DUPLEX_UNKNOWN;  	}  	ecmd->autoneg = AUTONEG_ENABLE; @@ -305,5 +305,5 @@ static const struct ethtool_ops atl1c_ethtool_ops = {  void atl1c_set_ethtool_ops(struct net_device *netdev)  { -	SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops); +	netdev->ethtool_ops = &atl1c_ethtool_ops;  } diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c index 3ef7092e3f1..1cda49a28f7 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_hw.c @@ -153,7 +153,7 @@ static int atl1c_get_permanent_address(struct atl1c_hw *hw)  bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value)  {  	int i; -	int ret = false; +	bool ret = false;  	u32 otp_ctrl_data;  	u32 control;  	u32 data; diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index a36a760ada2..e11bf18fbbd 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -145,9 +145,11 @@ static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag)  	 * Mask some pcie error bits  	 */  	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); -	pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); -	data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); -	pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); +	if (pos) { +		pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); +		data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); +		pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); +	}  	/* clear error status */  	pcie_capability_write_word(pdev, PCI_EXP_DEVSTA,  			PCI_EXP_DEVSTA_NFED | @@ -830,7 +832,7 @@ static int atl1c_sw_init(struct atl1c_adapter *adapter)  }  static inline void atl1c_clean_buffer(struct pci_dev *pdev, -				struct atl1c_buffer *buffer_info, int in_irq) +				struct atl1c_buffer *buffer_info)  {  	u16 pci_driection;  	if (buffer_info->flags & ATL1C_BUFFER_FREE) @@ -848,12 +850,8 @@ static inline void atl1c_clean_buffer(struct pci_dev *pdev,  			pci_unmap_page(pdev, buffer_info->dma,  					buffer_info->length, pci_driection);  	} -	if (buffer_info->skb) { -		if (in_irq) -			dev_kfree_skb_irq(buffer_info->skb); -		else -			dev_kfree_skb(buffer_info->skb); -	} +	if (buffer_info->skb) +		dev_consume_skb_any(buffer_info->skb);  	buffer_info->dma = 0;  	buffer_info->skb = NULL;  	ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); @@ -873,7 +871,7 @@ static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter,  	ring_count = tpd_ring->count;  	for (index = 0; index < ring_count; index++) {  		buffer_info = &tpd_ring->buffer_info[index]; -		atl1c_clean_buffer(pdev, buffer_info, 0); +		atl1c_clean_buffer(pdev, buffer_info);  	}  	/* Zero out Tx-buffers */ @@ -897,7 +895,7 @@ static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter)  	for (j = 0; j < rfd_ring->count; j++) {  		buffer_info = &rfd_ring->buffer_info[j]; -		atl1c_clean_buffer(pdev, buffer_info, 0); +		atl1c_clean_buffer(pdev, buffer_info);  	}  	/* zero out the descriptor ring */  	memset(rfd_ring->desc, 0, rfd_ring->size); @@ -1498,31 +1496,40 @@ static struct net_device_stats *atl1c_get_stats(struct net_device *netdev)  	struct net_device_stats *net_stats = &netdev->stats;  	atl1c_update_hw_stats(adapter); -	net_stats->rx_packets = hw_stats->rx_ok; -	net_stats->tx_packets = hw_stats->tx_ok;  	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;  	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;  	net_stats->multicast  = hw_stats->rx_mcast;  	net_stats->collisions = hw_stats->tx_1_col + -				hw_stats->tx_2_col * 2 + -				hw_stats->tx_late_col + hw_stats->tx_abort_col; -	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err + -				hw_stats->rx_len_err + hw_stats->rx_sz_ov + -				hw_stats->rx_rrd_ov + hw_stats->rx_align_err; +				hw_stats->tx_2_col + +				hw_stats->tx_late_col + +				hw_stats->tx_abort_col; + +	net_stats->rx_errors  = hw_stats->rx_frag + +				hw_stats->rx_fcs_err + +				hw_stats->rx_len_err + +				hw_stats->rx_sz_ov + +				hw_stats->rx_rrd_ov + +				hw_stats->rx_align_err + +				hw_stats->rx_rxf_ov; +  	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;  	net_stats->rx_length_errors = hw_stats->rx_len_err;  	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;  	net_stats->rx_frame_errors  = hw_stats->rx_align_err; -	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; +	net_stats->rx_dropped       = hw_stats->rx_rrd_ov; -	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; +	net_stats->tx_errors = hw_stats->tx_late_col + +			       hw_stats->tx_abort_col + +			       hw_stats->tx_underrun + +			       hw_stats->tx_trunc; -	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col + -				hw_stats->tx_underrun + hw_stats->tx_trunc;  	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;  	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;  	net_stats->tx_window_errors  = hw_stats->tx_late_col; +	net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors; +	net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors; +  	return net_stats;  } @@ -1551,7 +1558,7 @@ static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter,  	while (next_to_clean != hw_next_to_clean) {  		buffer_info = &tpd_ring->buffer_info[next_to_clean]; -		atl1c_clean_buffer(pdev, buffer_info, 1); +		atl1c_clean_buffer(pdev, buffer_info);  		if (++next_to_clean == tpd_ring->count)  			next_to_clean = 0;  		atomic_set(&tpd_ring->next_to_clean, next_to_clean); @@ -1966,17 +1973,17 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,  			  enum atl1c_trans_queue type)  {  	struct pci_dev *pdev = adapter->pdev; +	unsigned short offload_type;  	u8 hdr_len;  	u32 real_len; -	unsigned short offload_type; -	int err;  	if (skb_is_gso(skb)) { -		if (skb_header_cloned(skb)) { -			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -			if (unlikely(err)) -				return -1; -		} +		int err; + +		err = skb_cow_head(skb, 0); +		if (err < 0) +			return err; +  		offload_type = skb_shinfo(skb)->gso_type;  		if (offload_type & SKB_GSO_TCPV4) { @@ -2074,7 +2081,7 @@ static void atl1c_tx_rollback(struct atl1c_adapter *adpt,  	while (index != tpd_ring->next_to_use) {  		tpd = ATL1C_TPD_DESC(tpd_ring, index);  		buffer_info = &tpd_ring->buffer_info[index]; -		atl1c_clean_buffer(adpt->pdev, buffer_info, 0); +		atl1c_clean_buffer(adpt->pdev, buffer_info);  		memset(tpd, 0, sizeof(struct atl1c_tpd_desc));  		if (++index == tpd_ring->count)  			index = 0; @@ -2247,7 +2254,7 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,  		/* roll back tpd/buffer */  		atl1c_tx_rollback(adapter, tpd, type);  		spin_unlock_irqrestore(&adapter->tx_lock, flags); -		dev_kfree_skb(skb); +		dev_kfree_skb_any(skb);  	} else {  		atl1c_tx_queue(adapter, skb, tpd, type);  		spin_unlock_irqrestore(&adapter->tx_lock, flags); diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h index b5fd934585e..0212dac7e23 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e.h +++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h @@ -23,7 +23,6 @@  #ifndef _ATL1E_H_  #define _ATL1E_H_ -#include <linux/init.h>  #include <linux/interrupt.h>  #include <linux/types.h>  #include <linux/errno.h> @@ -499,10 +498,10 @@ struct atl1e_adapter {  extern char atl1e_driver_name[];  extern char atl1e_driver_version[]; -extern void atl1e_check_options(struct atl1e_adapter *adapter); -extern int atl1e_up(struct atl1e_adapter *adapter); -extern void atl1e_down(struct atl1e_adapter *adapter); -extern void atl1e_reinit_locked(struct atl1e_adapter *adapter); -extern s32 atl1e_reset_hw(struct atl1e_hw *hw); -extern void atl1e_set_ethtool_ops(struct net_device *netdev); +void atl1e_check_options(struct atl1e_adapter *adapter); +int atl1e_up(struct atl1e_adapter *adapter); +void atl1e_down(struct atl1e_adapter *adapter); +void atl1e_reinit_locked(struct atl1e_adapter *adapter); +s32 atl1e_reset_hw(struct atl1e_hw *hw); +void atl1e_set_ethtool_ops(struct net_device *netdev);  #endif /* _ATL1_E_H_ */ diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c index 82b23861bf5..1be072f4afc 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c @@ -57,8 +57,8 @@ static int atl1e_get_settings(struct net_device *netdev,  		else  			ecmd->duplex = DUPLEX_HALF;  	} else { -		ethtool_cmd_speed_set(ecmd, -1); -		ecmd->duplex = -1; +		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); +		ecmd->duplex = DUPLEX_UNKNOWN;  	}  	ecmd->autoneg = AUTONEG_ENABLE; @@ -388,5 +388,5 @@ static const struct ethtool_ops atl1e_ethtool_ops = {  void atl1e_set_ethtool_ops(struct net_device *netdev)  { -	SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops); +	netdev->ethtool_ops = &atl1e_ethtool_ops;  } diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 1966444590f..4345332533a 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -313,6 +313,34 @@ static void atl1e_set_multi(struct net_device *netdev)  	}  } +static void __atl1e_rx_mode(netdev_features_t features, u32 *mac_ctrl_data) +{ + +	if (features & NETIF_F_RXALL) { +		/* enable RX of ALL frames */ +		*mac_ctrl_data |= MAC_CTRL_DBG; +	} else { +		/* disable RX of ALL frames */ +		*mac_ctrl_data &= ~MAC_CTRL_DBG; +	} +} + +static void atl1e_rx_mode(struct net_device *netdev, +	netdev_features_t features) +{ +	struct atl1e_adapter *adapter = netdev_priv(netdev); +	u32 mac_ctrl_data = 0; + +	netdev_dbg(adapter->netdev, "%s\n", __func__); + +	atl1e_irq_disable(adapter); +	mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); +	__atl1e_rx_mode(features, &mac_ctrl_data); +	AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); +	atl1e_irq_enable(adapter); +} + +  static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data)  {  	if (features & NETIF_F_HW_VLAN_CTAG_RX) { @@ -394,6 +422,10 @@ static int atl1e_set_features(struct net_device *netdev,  	if (changed & NETIF_F_HW_VLAN_CTAG_RX)  		atl1e_vlan_mode(netdev, features); +	if (changed & NETIF_F_RXALL) +		atl1e_rx_mode(netdev, features); + +  	return 0;  } @@ -1057,7 +1089,8 @@ static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter)  		value |= MAC_CTRL_PROMIS_EN;  	if (netdev->flags & IFF_ALLMULTI)  		value |= MAC_CTRL_MC_ALL_EN; - +	if (netdev->features & NETIF_F_RXALL) +		value |= MAC_CTRL_DBG;  	AT_WRITE_REG(hw, REG_MAC_CTRL, value);  } @@ -1144,32 +1177,40 @@ static struct net_device_stats *atl1e_get_stats(struct net_device *netdev)  	struct atl1e_hw_stats  *hw_stats = &adapter->hw_stats;  	struct net_device_stats *net_stats = &netdev->stats; -	net_stats->rx_packets = hw_stats->rx_ok; -	net_stats->tx_packets = hw_stats->tx_ok;  	net_stats->rx_bytes   = hw_stats->rx_byte_cnt;  	net_stats->tx_bytes   = hw_stats->tx_byte_cnt;  	net_stats->multicast  = hw_stats->rx_mcast;  	net_stats->collisions = hw_stats->tx_1_col + -				hw_stats->tx_2_col * 2 + -				hw_stats->tx_late_col + hw_stats->tx_abort_col; +				hw_stats->tx_2_col + +				hw_stats->tx_late_col + +				hw_stats->tx_abort_col; + +	net_stats->rx_errors  = hw_stats->rx_frag + +				hw_stats->rx_fcs_err + +				hw_stats->rx_len_err + +				hw_stats->rx_sz_ov + +				hw_stats->rx_rrd_ov + +				hw_stats->rx_align_err + +				hw_stats->rx_rxf_ov; -	net_stats->rx_errors  = hw_stats->rx_frag + hw_stats->rx_fcs_err + -				hw_stats->rx_len_err + hw_stats->rx_sz_ov + -				hw_stats->rx_rrd_ov + hw_stats->rx_align_err;  	net_stats->rx_fifo_errors   = hw_stats->rx_rxf_ov;  	net_stats->rx_length_errors = hw_stats->rx_len_err;  	net_stats->rx_crc_errors    = hw_stats->rx_fcs_err;  	net_stats->rx_frame_errors  = hw_stats->rx_align_err; -	net_stats->rx_over_errors   = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; +	net_stats->rx_dropped       = hw_stats->rx_rrd_ov; -	net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; +	net_stats->tx_errors = hw_stats->tx_late_col + +			       hw_stats->tx_abort_col + +			       hw_stats->tx_underrun + +			       hw_stats->tx_trunc; -	net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col + -			       hw_stats->tx_underrun + hw_stats->tx_trunc;  	net_stats->tx_fifo_errors    = hw_stats->tx_underrun;  	net_stats->tx_aborted_errors = hw_stats->tx_abort_col;  	net_stats->tx_window_errors  = hw_stats->tx_late_col; +	net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors; +	net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors; +  	return net_stats;  } @@ -1405,7 +1446,8 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,  			rx_page_desc[que].rx_nxseq++;  			/* error packet */ -			if (prrs->pkt_flag & RRS_IS_ERR_FRAME) { +			if ((prrs->pkt_flag & RRS_IS_ERR_FRAME) && +			    !(netdev->features & NETIF_F_RXALL)) {  				if (prrs->err_flag & (RRS_ERR_BAD_CRC |  					RRS_ERR_DRIBBLE | RRS_ERR_CODE |  					RRS_ERR_TRUNC)) { @@ -1418,7 +1460,10 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,  			}  			packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) & -					RRS_PKT_SIZE_MASK) - 4; /* CRC */ +					RRS_PKT_SIZE_MASK); +			if (likely(!(netdev->features & NETIF_F_RXFCS))) +				packet_size -= 4; /* CRC */ +  			skb = netdev_alloc_skb_ip_align(netdev, packet_size);  			if (skb == NULL)  				goto skip_pkt; @@ -1596,17 +1641,17 @@ static u16 atl1e_cal_tdp_req(const struct sk_buff *skb)  static int atl1e_tso_csum(struct atl1e_adapter *adapter,  		       struct sk_buff *skb, struct atl1e_tpd_desc *tpd)  { +	unsigned short offload_type;  	u8 hdr_len;  	u32 real_len; -	unsigned short offload_type; -	int err;  	if (skb_is_gso(skb)) { -		if (skb_header_cloned(skb)) { -			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -			if (unlikely(err)) -				return -1; -		} +		int err; + +		err = skb_cow_head(skb, 0); +		if (err < 0) +			return err; +  		offload_type = skb_shinfo(skb)->gso_type;  		if (offload_type & SKB_GSO_TCPV4) { @@ -2245,7 +2290,8 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)  			      NETIF_F_HW_VLAN_CTAG_RX;  	netdev->features = netdev->hw_features | NETIF_F_LLTX |  			   NETIF_F_HW_VLAN_CTAG_TX; - +	/* not enabled by default */ +	netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS;  	return 0;  } @@ -2390,7 +2436,7 @@ err_reset:  err_register:  err_sw_init:  err_eeprom: -	iounmap(adapter->hw.hw_addr); +	pci_iounmap(pdev, adapter->hw.hw_addr);  err_init_netdev:  err_ioremap:  	free_netdev(netdev); @@ -2428,7 +2474,7 @@ static void atl1e_remove(struct pci_dev *pdev)  	unregister_netdev(netdev);  	atl1e_free_ring_resources(adapter);  	atl1e_force_ps(&adapter->hw); -	iounmap(adapter->hw.hw_addr); +	pci_iounmap(pdev, adapter->hw.hw_addr);  	pci_release_regions(pdev);  	free_netdev(netdev);  	pci_disable_device(pdev); diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 538211d6f7d..b460db7919a 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -1678,33 +1678,42 @@ static void atl1_inc_smb(struct atl1_adapter *adapter)  	struct net_device *netdev = adapter->netdev;  	struct stats_msg_block *smb = adapter->smb.smb; +	u64 new_rx_errors = smb->rx_frag + +			    smb->rx_fcs_err + +			    smb->rx_len_err + +			    smb->rx_sz_ov + +			    smb->rx_rxf_ov + +			    smb->rx_rrd_ov + +			    smb->rx_align_err; +	u64 new_tx_errors = smb->tx_late_col + +			    smb->tx_abort_col + +			    smb->tx_underrun + +			    smb->tx_trunc; +  	/* Fill out the OS statistics structure */ -	adapter->soft_stats.rx_packets += smb->rx_ok; -	adapter->soft_stats.tx_packets += smb->tx_ok; +	adapter->soft_stats.rx_packets += smb->rx_ok + new_rx_errors; +	adapter->soft_stats.tx_packets += smb->tx_ok + new_tx_errors;  	adapter->soft_stats.rx_bytes += smb->rx_byte_cnt;  	adapter->soft_stats.tx_bytes += smb->tx_byte_cnt;  	adapter->soft_stats.multicast += smb->rx_mcast; -	adapter->soft_stats.collisions += (smb->tx_1_col + smb->tx_2_col * 2 + -		smb->tx_late_col + smb->tx_abort_col * adapter->hw.max_retry); +	adapter->soft_stats.collisions += smb->tx_1_col + +					  smb->tx_2_col + +					  smb->tx_late_col + +					  smb->tx_abort_col;  	/* Rx Errors */ -	adapter->soft_stats.rx_errors += (smb->rx_frag + smb->rx_fcs_err + -		smb->rx_len_err + smb->rx_sz_ov + smb->rx_rxf_ov + -		smb->rx_rrd_ov + smb->rx_align_err); +	adapter->soft_stats.rx_errors += new_rx_errors;  	adapter->soft_stats.rx_fifo_errors += smb->rx_rxf_ov;  	adapter->soft_stats.rx_length_errors += smb->rx_len_err;  	adapter->soft_stats.rx_crc_errors += smb->rx_fcs_err;  	adapter->soft_stats.rx_frame_errors += smb->rx_align_err; -	adapter->soft_stats.rx_missed_errors += (smb->rx_rrd_ov + -		smb->rx_rxf_ov);  	adapter->soft_stats.rx_pause += smb->rx_pause;  	adapter->soft_stats.rx_rrd_ov += smb->rx_rrd_ov;  	adapter->soft_stats.rx_trunc += smb->rx_sz_ov;  	/* Tx Errors */ -	adapter->soft_stats.tx_errors += (smb->tx_late_col + -		smb->tx_abort_col + smb->tx_underrun + smb->tx_trunc); +	adapter->soft_stats.tx_errors += new_tx_errors;  	adapter->soft_stats.tx_fifo_errors += smb->tx_underrun;  	adapter->soft_stats.tx_aborted_errors += smb->tx_abort_col;  	adapter->soft_stats.tx_window_errors += smb->tx_late_col; @@ -1718,23 +1727,18 @@ static void atl1_inc_smb(struct atl1_adapter *adapter)  	adapter->soft_stats.tx_trunc += smb->tx_trunc;  	adapter->soft_stats.tx_pause += smb->tx_pause; -	netdev->stats.rx_packets = adapter->soft_stats.rx_packets; -	netdev->stats.tx_packets = adapter->soft_stats.tx_packets;  	netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;  	netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;  	netdev->stats.multicast = adapter->soft_stats.multicast;  	netdev->stats.collisions = adapter->soft_stats.collisions;  	netdev->stats.rx_errors = adapter->soft_stats.rx_errors; -	netdev->stats.rx_over_errors = -		adapter->soft_stats.rx_missed_errors;  	netdev->stats.rx_length_errors =  		adapter->soft_stats.rx_length_errors;  	netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;  	netdev->stats.rx_frame_errors =  		adapter->soft_stats.rx_frame_errors;  	netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors; -	netdev->stats.rx_missed_errors = -		adapter->soft_stats.rx_missed_errors; +	netdev->stats.rx_dropped = adapter->soft_stats.rx_rrd_ov;  	netdev->stats.tx_errors = adapter->soft_stats.tx_errors;  	netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;  	netdev->stats.tx_aborted_errors = @@ -1743,6 +1747,9 @@ static void atl1_inc_smb(struct atl1_adapter *adapter)  		adapter->soft_stats.tx_window_errors;  	netdev->stats.tx_carrier_errors =  		adapter->soft_stats.tx_carrier_errors; + +	netdev->stats.rx_packets = adapter->soft_stats.rx_packets; +	netdev->stats.tx_packets = adapter->soft_stats.tx_packets;  }  static void atl1_update_mailbox(struct atl1_adapter *adapter) @@ -1872,7 +1879,7 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)  						adapter->rx_buffer_len);  		if (unlikely(!skb)) {  			/* Better luck next round */ -			adapter->netdev->stats.rx_dropped++; +			adapter->soft_stats.rx_dropped++;  			break;  		} @@ -2111,18 +2118,17 @@ static u16 atl1_tpd_avail(struct atl1_tpd_ring *tpd_ring)  }  static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb, -	struct tx_packet_desc *ptpd) +		    struct tx_packet_desc *ptpd)  {  	u8 hdr_len, ip_off;  	u32 real_len; -	int err;  	if (skb_shinfo(skb)->gso_size) { -		if (skb_header_cloned(skb)) { -			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); -			if (unlikely(err)) -				return -1; -		} +		int err; + +		err = skb_cow_head(skb, 0); +		if (err < 0) +			return err;  		if (skb->protocol == htons(ETH_P_IP)) {  			struct iphdr *iph = ip_hdr(skb); @@ -2168,7 +2174,7 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,  			return 3;  		}  	} -	return false; +	return 0;  }  static int atl1_tx_csum(struct atl1_adapter *adapter, struct sk_buff *skb, @@ -3122,7 +3128,8 @@ static void atl1_remove(struct pci_dev *pdev)  	 * from the BIOS during POST.  If we've been messing with the MAC  	 * address, we need to save the permanent one.  	 */ -	if (memcmp(adapter->hw.mac_addr, adapter->hw.perm_mac_addr, ETH_ALEN)) { +	if (!ether_addr_equal_unaligned(adapter->hw.mac_addr, +					adapter->hw.perm_mac_addr)) {  		memcpy(adapter->hw.mac_addr, adapter->hw.perm_mac_addr,  			ETH_ALEN);  		atl1_set_mac_addr(&adapter->hw); @@ -3251,8 +3258,8 @@ static int atl1_get_settings(struct net_device *netdev,  		else  			ecmd->duplex = DUPLEX_HALF;  	} else { -		ethtool_cmd_speed_set(ecmd, -1); -		ecmd->duplex = -1; +		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); +		ecmd->duplex = DUPLEX_UNKNOWN;  	}  	if (hw->media_type == MEDIA_TYPE_AUTO_SENSOR ||  	    hw->media_type == MEDIA_TYPE_1000M_FULL) diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h index 3bf79a56220..34a58cd846a 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.h +++ b/drivers/net/ethernet/atheros/atlx/atl1.h @@ -666,6 +666,7 @@ struct atl1_sft_stats {  	u64 rx_errors;  	u64 rx_length_errors;  	u64 rx_crc_errors; +	u64 rx_dropped;  	u64 rx_frame_errors;  	u64 rx_fifo_errors;  	u64 rx_missed_errors; diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c index 265ce1b752e..6746bd71714 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.c +++ b/drivers/net/ethernet/atheros/atlx/atl2.c @@ -55,6 +55,7 @@ static const char atl2_driver_name[] = "atl2";  static const char atl2_driver_string[] = "Atheros(R) L2 Ethernet Driver";  static const char atl2_copyright[] = "Copyright (c) 2007 Atheros Corporation.";  static const char atl2_driver_version[] = ATL2_DRV_VERSION; +static const struct ethtool_ops atl2_ethtool_ops;  MODULE_AUTHOR("Atheros Corporation <xiong.huang@atheros.com>, Chris Snook <csnook@redhat.com>");  MODULE_DESCRIPTION("Atheros Fast Ethernet Network Driver"); @@ -71,8 +72,6 @@ static DEFINE_PCI_DEVICE_TABLE(atl2_pci_tbl) = {  };  MODULE_DEVICE_TABLE(pci, atl2_pci_tbl); -static void atl2_set_ethtool_ops(struct net_device *netdev); -  static void atl2_check_options(struct atl2_adapter *adapter);  /** @@ -1397,7 +1396,7 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	atl2_setup_pcicmd(pdev);  	netdev->netdev_ops = &atl2_netdev_ops; -	atl2_set_ethtool_ops(netdev); +	netdev->ethtool_ops = &atl2_ethtool_ops;  	netdev->watchdog_timeo = 5 * HZ;  	strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); @@ -1770,8 +1769,8 @@ static int atl2_get_settings(struct net_device *netdev,  		else  			ecmd->duplex = DUPLEX_HALF;  	} else { -		ethtool_cmd_speed_set(ecmd, -1); -		ecmd->duplex = -1; +		ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); +		ecmd->duplex = DUPLEX_UNKNOWN;  	}  	ecmd->autoneg = AUTONEG_ENABLE; @@ -2105,11 +2104,6 @@ static const struct ethtool_ops atl2_ethtool_ops = {  	.set_eeprom		= atl2_set_eeprom,  }; -static void atl2_set_ethtool_ops(struct net_device *netdev) -{ -	SET_ETHTOOL_OPS(netdev, &atl2_ethtool_ops); -} -  #define LBYTESWAP(a)  ((((a) & 0x00ff00ff) << 8) | \  	(((a) & 0xff00ff00) >> 8))  #define LONGSWAP(a)   ((LBYTESWAP(a) << 16) | (LBYTESWAP(a) >> 16)) diff --git a/drivers/net/ethernet/atheros/atlx/atl2.h b/drivers/net/ethernet/atheros/atlx/atl2.h index 3ebe19f7242..2f27d4c4c3a 100644 --- a/drivers/net/ethernet/atheros/atlx/atl2.h +++ b/drivers/net/ethernet/atheros/atlx/atl2.h @@ -42,7 +42,7 @@  #include "atlx.h"  #ifdef ETHTOOL_OPS_COMPAT -extern int ethtool_ioctl(struct ifreq *ifr); +int ethtool_ioctl(struct ifreq *ifr);  #endif  #define PCI_COMMAND_REGISTER	PCI_COMMAND  | 
