diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
| -rw-r--r-- | drivers/net/forcedeth.c | 114 | 
1 files changed, 42 insertions, 72 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index d5ab4dad505..537b6957bb7 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -64,6 +64,7 @@  #include <linux/dma-mapping.h>  #include <linux/slab.h>  #include <linux/uaccess.h> +#include <linux/prefetch.h>  #include  <linux/io.h>  #include <asm/irq.h> @@ -774,7 +775,6 @@ struct fe_priv {  	u32 driver_data;  	u32 device_id;  	u32 register_size; -	int rx_csum;  	u32 mac_in_use;  	int mgmt_version;  	int mgmt_sema; @@ -3956,6 +3956,7 @@ static int nv_set_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)  static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  {  	struct fe_priv *np = netdev_priv(dev); +	u32 speed;  	int adv;  	spin_lock_irq(&np->lock); @@ -3975,23 +3976,26 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  	if (netif_carrier_ok(dev)) {  		switch (np->linkspeed & (NVREG_LINKSPEED_MASK)) {  		case NVREG_LINKSPEED_10: -			ecmd->speed = SPEED_10; +			speed = SPEED_10;  			break;  		case NVREG_LINKSPEED_100: -			ecmd->speed = SPEED_100; +			speed = SPEED_100;  			break;  		case NVREG_LINKSPEED_1000: -			ecmd->speed = SPEED_1000; +			speed = SPEED_1000; +			break; +		default: +			speed = -1;  			break;  		}  		ecmd->duplex = DUPLEX_HALF;  		if (np->duplex)  			ecmd->duplex = DUPLEX_FULL;  	} else { -		ecmd->speed = -1; +		speed = -1;  		ecmd->duplex = -1;  	} - +	ethtool_cmd_speed_set(ecmd, speed);  	ecmd->autoneg = np->autoneg;  	ecmd->advertising = ADVERTISED_MII; @@ -4030,6 +4034,7 @@ static int nv_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  {  	struct fe_priv *np = netdev_priv(dev); +	u32 speed = ethtool_cmd_speed(ecmd);  	if (ecmd->port != PORT_MII)  		return -EINVAL; @@ -4055,7 +4060,7 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  		/* Note: autonegotiation disable, speed 1000 intentionally  		 * forbidden - no one should need that. */ -		if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100) +		if (speed != SPEED_10 && speed != SPEED_100)  			return -EINVAL;  		if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)  			return -EINVAL; @@ -4139,13 +4144,13 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)  		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);  		adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4 | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); -		if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF) +		if (speed == SPEED_10 && ecmd->duplex == DUPLEX_HALF)  			adv |= ADVERTISE_10HALF; -		if (ecmd->speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL) +		if (speed == SPEED_10 && ecmd->duplex == DUPLEX_FULL)  			adv |= ADVERTISE_10FULL; -		if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF) +		if (speed == SPEED_100 && ecmd->duplex == DUPLEX_HALF)  			adv |= ADVERTISE_100HALF; -		if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL) +		if (speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)  			adv |= ADVERTISE_100FULL;  		np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);  		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisements but disable tx pause */ @@ -4264,16 +4269,6 @@ static int nv_nway_reset(struct net_device *dev)  	return ret;  } -static int nv_set_tso(struct net_device *dev, u32 value) -{ -	struct fe_priv *np = netdev_priv(dev); - -	if ((np->driver_data & DEV_HAS_CHECKSUM)) -		return ethtool_op_set_tso(dev, value); -	else -		return -EOPNOTSUPP; -} -  static void nv_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring)  {  	struct fe_priv *np = netdev_priv(dev); @@ -4480,58 +4475,36 @@ static int nv_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam*  	return 0;  } -static u32 nv_get_rx_csum(struct net_device *dev) +static u32 nv_fix_features(struct net_device *dev, u32 features)  { -	struct fe_priv *np = netdev_priv(dev); -	return np->rx_csum != 0; +	/* vlan is dependent on rx checksum offload */ +	if (features & (NETIF_F_HW_VLAN_TX|NETIF_F_HW_VLAN_RX)) +		features |= NETIF_F_RXCSUM; + +	return features;  } -static int nv_set_rx_csum(struct net_device *dev, u32 data) +static int nv_set_features(struct net_device *dev, u32 features)  {  	struct fe_priv *np = netdev_priv(dev);  	u8 __iomem *base = get_hwbase(dev); -	int retcode = 0; - -	if (np->driver_data & DEV_HAS_CHECKSUM) { -		if (data) { -			np->rx_csum = 1; -			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; -		} else { -			np->rx_csum = 0; -			/* vlan is dependent on rx checksum offload */ -			if (!(np->vlanctl_bits & NVREG_VLANCONTROL_ENABLE)) -				np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK; -		} -		if (netif_running(dev)) { -			spin_lock_irq(&np->lock); -			writel(np->txrxctl_bits, base + NvRegTxRxControl); -			spin_unlock_irq(&np->lock); -		} -	} else { -		return -EINVAL; -	} +	u32 changed = dev->features ^ features; -	return retcode; -} +	if (changed & NETIF_F_RXCSUM) { +		spin_lock_irq(&np->lock); -static int nv_set_tx_csum(struct net_device *dev, u32 data) -{ -	struct fe_priv *np = netdev_priv(dev); +		if (features & NETIF_F_RXCSUM) +			np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; +		else +			np->txrxctl_bits &= ~NVREG_TXRXCTL_RXCHECK; -	if (np->driver_data & DEV_HAS_CHECKSUM) -		return ethtool_op_set_tx_csum(dev, data); -	else -		return -EOPNOTSUPP; -} +		if (netif_running(dev)) +			writel(np->txrxctl_bits, base + NvRegTxRxControl); -static int nv_set_sg(struct net_device *dev, u32 data) -{ -	struct fe_priv *np = netdev_priv(dev); +		spin_unlock_irq(&np->lock); +	} -	if (np->driver_data & DEV_HAS_CHECKSUM) -		return ethtool_op_set_sg(dev, data); -	else -		return -EOPNOTSUPP; +	return 0;  }  static int nv_get_sset_count(struct net_device *dev, int sset) @@ -4896,15 +4869,10 @@ static const struct ethtool_ops ops = {  	.get_regs_len = nv_get_regs_len,  	.get_regs = nv_get_regs,  	.nway_reset = nv_nway_reset, -	.set_tso = nv_set_tso,  	.get_ringparam = nv_get_ringparam,  	.set_ringparam = nv_set_ringparam,  	.get_pauseparam = nv_get_pauseparam,  	.set_pauseparam = nv_set_pauseparam, -	.get_rx_csum = nv_get_rx_csum, -	.set_rx_csum = nv_set_rx_csum, -	.set_tx_csum = nv_set_tx_csum, -	.set_sg = nv_set_sg,  	.get_strings = nv_get_strings,  	.get_ethtool_stats = nv_get_ethtool_stats,  	.get_sset_count = nv_get_sset_count, @@ -5235,6 +5203,8 @@ static const struct net_device_ops nv_netdev_ops = {  	.ndo_start_xmit		= nv_start_xmit,  	.ndo_tx_timeout		= nv_tx_timeout,  	.ndo_change_mtu		= nv_change_mtu, +	.ndo_fix_features	= nv_fix_features, +	.ndo_set_features	= nv_set_features,  	.ndo_validate_addr	= eth_validate_addr,  	.ndo_set_mac_address	= nv_set_mac_address,  	.ndo_set_multicast_list	= nv_set_multicast, @@ -5251,6 +5221,8 @@ static const struct net_device_ops nv_netdev_ops_optimized = {  	.ndo_start_xmit		= nv_start_xmit_optimized,  	.ndo_tx_timeout		= nv_tx_timeout,  	.ndo_change_mtu		= nv_change_mtu, +	.ndo_fix_features	= nv_fix_features, +	.ndo_set_features	= nv_set_features,  	.ndo_validate_addr	= eth_validate_addr,  	.ndo_set_mac_address	= nv_set_mac_address,  	.ndo_set_multicast_list	= nv_set_multicast, @@ -5364,11 +5336,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i  		np->pkt_limit = NV_PKTLIMIT_2;  	if (id->driver_data & DEV_HAS_CHECKSUM) { -		np->rx_csum = 1;  		np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; -		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; -		dev->features |= NETIF_F_TSO; -		dev->features |= NETIF_F_GRO; +		dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_SG | +			NETIF_F_TSO | NETIF_F_RXCSUM; +		dev->features |= dev->hw_features;  	}  	np->vlanctl_bits = 0; @@ -5384,7 +5355,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i  		np->pause_flags |= NV_PAUSEFRAME_TX_CAPABLE | NV_PAUSEFRAME_TX_REQ;  	} -  	err = -ENOMEM;  	np->base = ioremap(addr, np->register_size);  	if (!np->base)  |