diff options
Diffstat (limited to 'drivers/net/pcnet32.c')
| -rw-r--r-- | drivers/net/pcnet32.c | 90 | 
1 files changed, 36 insertions, 54 deletions
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index 768037602df..b48aba9e422 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -295,12 +295,14 @@ struct pcnet32_private {  	struct net_device	*next;  	struct mii_if_info	mii_if;  	struct timer_list	watchdog_timer; -	struct timer_list	blink_timer;  	u32			msg_enable;	/* debug message level */  	/* each bit indicates an available PHY */  	u32			phymask;  	unsigned short		chip_version;	/* which variant this is */ + +	/* saved registers during ethtool blink */ +	u16 			save_regs[4];  };  static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); @@ -324,8 +326,6 @@ static void pcnet32_restart(struct net_device *dev, unsigned int csr0_bits);  static void pcnet32_ethtool_test(struct net_device *dev,  				 struct ethtool_test *eth_test, u64 * data);  static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1); -static int pcnet32_phys_id(struct net_device *dev, u32 data); -static void pcnet32_led_blink_callback(struct net_device *dev);  static int pcnet32_get_regs_len(struct net_device *dev);  static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,  			     void *ptr); @@ -1022,7 +1022,8 @@ clean_up:  	return rc;  }				/* end pcnet32_loopback_test  */ -static void pcnet32_led_blink_callback(struct net_device *dev) +static int pcnet32_set_phys_id(struct net_device *dev, +			       enum ethtool_phys_id_state state)  {  	struct pcnet32_private *lp = netdev_priv(dev);  	struct pcnet32_access *a = &lp->a; @@ -1030,50 +1031,31 @@ static void pcnet32_led_blink_callback(struct net_device *dev)  	unsigned long flags;  	int i; -	spin_lock_irqsave(&lp->lock, flags); -	for (i = 4; i < 8; i++) -		a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); -	spin_unlock_irqrestore(&lp->lock, flags); - -	mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); -} +	switch (state) { +	case ETHTOOL_ID_ACTIVE: +		/* Save the current value of the bcrs */ +		spin_lock_irqsave(&lp->lock, flags); +		for (i = 4; i < 8; i++) +			lp->save_regs[i - 4] = a->read_bcr(ioaddr, i); +		spin_unlock_irqrestore(&lp->lock, flags); +		return 2;	/* cycle on/off twice per second */ -static int pcnet32_phys_id(struct net_device *dev, u32 data) -{ -	struct pcnet32_private *lp = netdev_priv(dev); -	struct pcnet32_access *a = &lp->a; -	ulong ioaddr = dev->base_addr; -	unsigned long flags; -	int i, regs[4]; +	case ETHTOOL_ID_ON: +	case ETHTOOL_ID_OFF: +		/* Blink the led */ +		spin_lock_irqsave(&lp->lock, flags); +		for (i = 4; i < 8; i++) +			a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); +		spin_unlock_irqrestore(&lp->lock, flags); +		break; -	if (!lp->blink_timer.function) { -		init_timer(&lp->blink_timer); -		lp->blink_timer.function = (void *)pcnet32_led_blink_callback; -		lp->blink_timer.data = (unsigned long)dev; +	case ETHTOOL_ID_INACTIVE: +		/* Restore the original value of the bcrs */ +		spin_lock_irqsave(&lp->lock, flags); +		for (i = 4; i < 8; i++) +			a->write_bcr(ioaddr, i, lp->save_regs[i - 4]); +		spin_unlock_irqrestore(&lp->lock, flags);  	} - -	/* Save the current value of the bcrs */ -	spin_lock_irqsave(&lp->lock, flags); -	for (i = 4; i < 8; i++) -		regs[i - 4] = a->read_bcr(ioaddr, i); -	spin_unlock_irqrestore(&lp->lock, flags); - -	mod_timer(&lp->blink_timer, jiffies); -	set_current_state(TASK_INTERRUPTIBLE); - -	/* AV: the limit here makes no sense whatsoever */ -	if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ))) -		data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ); - -	msleep_interruptible(data * 1000); -	del_timer_sync(&lp->blink_timer); - -	/* Restore the original value of the bcrs */ -	spin_lock_irqsave(&lp->lock, flags); -	for (i = 4; i < 8; i++) -		a->write_bcr(ioaddr, i, regs[i - 4]); -	spin_unlock_irqrestore(&lp->lock, flags); -  	return 0;  } @@ -1450,7 +1432,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {  	.set_ringparam		= pcnet32_set_ringparam,  	.get_strings		= pcnet32_get_strings,  	.self_test		= pcnet32_ethtool_test, -	.phys_id		= pcnet32_phys_id, +	.set_phys_id		= pcnet32_set_phys_id,  	.get_regs_len		= pcnet32_get_regs_len,  	.get_regs		= pcnet32_get_regs,  	.get_sset_count		= pcnet32_get_sset_count, @@ -2117,7 +2099,7 @@ static int pcnet32_open(struct net_device *dev)  		int first_phy = -1;  		u16 bmcr;  		u32 bcr9; -		struct ethtool_cmd ecmd; +		struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };  		/*  		 * There is really no good other way to handle multiple PHYs @@ -2133,9 +2115,9 @@ static int pcnet32_open(struct net_device *dev)  			ecmd.port = PORT_MII;  			ecmd.transceiver = XCVR_INTERNAL;  			ecmd.autoneg = AUTONEG_DISABLE; -			ecmd.speed = -			    lp-> -			    options & PCNET32_PORT_100 ? SPEED_100 : SPEED_10; +			ethtool_cmd_speed_set(&ecmd, +					      (lp->options & PCNET32_PORT_100) ? +					      SPEED_100 : SPEED_10);  			bcr9 = lp->a.read_bcr(ioaddr, 9);  			if (lp->options & PCNET32_PORT_FD) { @@ -2781,11 +2763,11 @@ static void pcnet32_check_media(struct net_device *dev, int verbose)  		netif_carrier_on(dev);  		if (lp->mii) {  			if (netif_msg_link(lp)) { -				struct ethtool_cmd ecmd; +				struct ethtool_cmd ecmd = { +					.cmd = ETHTOOL_GSET };  				mii_ethtool_gset(&lp->mii_if, &ecmd); -				netdev_info(dev, "link up, %sMbps, %s-duplex\n", -					    (ecmd.speed == SPEED_100) -					    ? "100" : "10", +				netdev_info(dev, "link up, %uMbps, %s-duplex\n", +					    ethtool_cmd_speed(&ecmd),  					    (ecmd.duplex == DUPLEX_FULL)  					    ? "full" : "half");  			}  |