aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/pcnet32.c74
1 files changed, 28 insertions, 46 deletions
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index aee3bb0358bf..eb7ac4e48c71 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -295,12 +295,14 @@ struct pcnet32_private {
295 struct net_device *next; 295 struct net_device *next;
296 struct mii_if_info mii_if; 296 struct mii_if_info mii_if;
297 struct timer_list watchdog_timer; 297 struct timer_list watchdog_timer;
298 struct timer_list blink_timer;
299 u32 msg_enable; /* debug message level */ 298 u32 msg_enable; /* debug message level */
300 299
301 /* each bit indicates an available PHY */ 300 /* each bit indicates an available PHY */
302 u32 phymask; 301 u32 phymask;
303 unsigned short chip_version; /* which variant this is */ 302 unsigned short chip_version; /* which variant this is */
303
304 /* saved registers during ethtool blink */
305 u16 save_regs[4];
304}; 306};
305 307
306static int pcnet32_probe_pci(struct pci_dev *, const struct pci_device_id *); 308static 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);
324static void pcnet32_ethtool_test(struct net_device *dev, 326static void pcnet32_ethtool_test(struct net_device *dev,
325 struct ethtool_test *eth_test, u64 * data); 327 struct ethtool_test *eth_test, u64 * data);
326static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1); 328static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1);
327static int pcnet32_phys_id(struct net_device *dev, u32 data);
328static void pcnet32_led_blink_callback(struct net_device *dev);
329static int pcnet32_get_regs_len(struct net_device *dev); 329static int pcnet32_get_regs_len(struct net_device *dev);
330static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, 330static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
331 void *ptr); 331 void *ptr);
@@ -1022,7 +1022,8 @@ clean_up:
1022 return rc; 1022 return rc;
1023} /* end pcnet32_loopback_test */ 1023} /* end pcnet32_loopback_test */
1024 1024
1025static void pcnet32_led_blink_callback(struct net_device *dev) 1025static int pcnet32_set_phys_id(struct net_device *dev,
1026 enum ethtool_phys_id_state state)
1026{ 1027{
1027 struct pcnet32_private *lp = netdev_priv(dev); 1028 struct pcnet32_private *lp = netdev_priv(dev);
1028 struct pcnet32_access *a = &lp->a; 1029 struct pcnet32_access *a = &lp->a;
@@ -1030,50 +1031,31 @@ static void pcnet32_led_blink_callback(struct net_device *dev)
1030 unsigned long flags; 1031 unsigned long flags;
1031 int i; 1032 int i;
1032 1033
1033 spin_lock_irqsave(&lp->lock, flags); 1034 switch (state) {
1034 for (i = 4; i < 8; i++) 1035 case ETHTOOL_ID_ACTIVE:
1035 a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000); 1036 /* Save the current value of the bcrs */
1036 spin_unlock_irqrestore(&lp->lock, flags); 1037 spin_lock_irqsave(&lp->lock, flags);
1037 1038 for (i = 4; i < 8; i++)
1038 mod_timer(&lp->blink_timer, PCNET32_BLINK_TIMEOUT); 1039 lp->save_regs[i - 4] = a->read_bcr(ioaddr, i);
1039} 1040 spin_unlock_irqrestore(&lp->lock, flags);
1041 return -EINVAL;
1040 1042
1041static int pcnet32_phys_id(struct net_device *dev, u32 data) 1043 case ETHTOOL_ID_ON:
1042{ 1044 case ETHTOOL_ID_OFF:
1043 struct pcnet32_private *lp = netdev_priv(dev); 1045 /* Blink the led */
1044 struct pcnet32_access *a = &lp->a; 1046 spin_lock_irqsave(&lp->lock, flags);
1045 ulong ioaddr = dev->base_addr; 1047 for (i = 4; i < 8; i++)
1046 unsigned long flags; 1048 a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
1047 int i, regs[4]; 1049 spin_unlock_irqrestore(&lp->lock, flags);
1050 break;
1048 1051
1049 if (!lp->blink_timer.function) { 1052 case ETHTOOL_ID_INACTIVE:
1050 init_timer(&lp->blink_timer); 1053 /* Restore the original value of the bcrs */
1051 lp->blink_timer.function = (void *)pcnet32_led_blink_callback; 1054 spin_lock_irqsave(&lp->lock, flags);
1052 lp->blink_timer.data = (unsigned long)dev; 1055 for (i = 4; i < 8; i++)
1056 a->write_bcr(ioaddr, i, lp->save_regs[i - 4]);
1057 spin_unlock_irqrestore(&lp->lock, flags);
1053 } 1058 }
1054
1055 /* Save the current value of the bcrs */
1056 spin_lock_irqsave(&lp->lock, flags);
1057 for (i = 4; i < 8; i++)
1058 regs[i - 4] = a->read_bcr(ioaddr, i);
1059 spin_unlock_irqrestore(&lp->lock, flags);
1060
1061 mod_timer(&lp->blink_timer, jiffies);
1062 set_current_state(TASK_INTERRUPTIBLE);
1063
1064 /* AV: the limit here makes no sense whatsoever */
1065 if ((!data) || (data > (u32) (MAX_SCHEDULE_TIMEOUT / HZ)))
1066 data = (u32) (MAX_SCHEDULE_TIMEOUT / HZ);
1067
1068 msleep_interruptible(data * 1000);
1069 del_timer_sync(&lp->blink_timer);
1070
1071 /* Restore the original value of the bcrs */
1072 spin_lock_irqsave(&lp->lock, flags);
1073 for (i = 4; i < 8; i++)
1074 a->write_bcr(ioaddr, i, regs[i - 4]);
1075 spin_unlock_irqrestore(&lp->lock, flags);
1076
1077 return 0; 1059 return 0;
1078} 1060}
1079 1061
@@ -1450,7 +1432,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {
1450 .set_ringparam = pcnet32_set_ringparam, 1432 .set_ringparam = pcnet32_set_ringparam,
1451 .get_strings = pcnet32_get_strings, 1433 .get_strings = pcnet32_get_strings,
1452 .self_test = pcnet32_ethtool_test, 1434 .self_test = pcnet32_ethtool_test,
1453 .phys_id = pcnet32_phys_id, 1435 .set_phys_id = pcnet32_set_phys_id,
1454 .get_regs_len = pcnet32_get_regs_len, 1436 .get_regs_len = pcnet32_get_regs_len,
1455 .get_regs = pcnet32_get_regs, 1437 .get_regs = pcnet32_get_regs,
1456 .get_sset_count = pcnet32_get_sset_count, 1438 .get_sset_count = pcnet32_get_sset_count,