aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/forcedeth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r--drivers/net/forcedeth.c49
1 files changed, 41 insertions, 8 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 36342230a6de..d4843d014bc9 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -323,8 +323,8 @@ enum {
323 NvRegMIIStatus = 0x180, 323 NvRegMIIStatus = 0x180,
324#define NVREG_MIISTAT_ERROR 0x0001 324#define NVREG_MIISTAT_ERROR 0x0001
325#define NVREG_MIISTAT_LINKCHANGE 0x0008 325#define NVREG_MIISTAT_LINKCHANGE 0x0008
326#define NVREG_MIISTAT_MASK 0x000f 326#define NVREG_MIISTAT_MASK_RW 0x0007
327#define NVREG_MIISTAT_MASK2 0x000f 327#define NVREG_MIISTAT_MASK_ALL 0x000f
328 NvRegMIIMask = 0x184, 328 NvRegMIIMask = 0x184,
329#define NVREG_MII_LINKCHANGE 0x0008 329#define NVREG_MII_LINKCHANGE 0x0008
330 330
@@ -624,6 +624,9 @@ union ring_type {
624#define NV_MSI_X_VECTOR_TX 0x1 624#define NV_MSI_X_VECTOR_TX 0x1
625#define NV_MSI_X_VECTOR_OTHER 0x2 625#define NV_MSI_X_VECTOR_OTHER 0x2
626 626
627#define NV_RESTART_TX 0x1
628#define NV_RESTART_RX 0x2
629
627/* statistics */ 630/* statistics */
628struct nv_ethtool_str { 631struct nv_ethtool_str {
629 char name[ETH_GSTRING_LEN]; 632 char name[ETH_GSTRING_LEN];
@@ -1061,7 +1064,7 @@ static int mii_rw(struct net_device *dev, int addr, int miireg, int value)
1061 u32 reg; 1064 u32 reg;
1062 int retval; 1065 int retval;
1063 1066
1064 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); 1067 writel(NVREG_MIISTAT_MASK_RW, base + NvRegMIIStatus);
1065 1068
1066 reg = readl(base + NvRegMIIControl); 1069 reg = readl(base + NvRegMIIControl);
1067 if (reg & NVREG_MIICTL_INUSE) { 1070 if (reg & NVREG_MIICTL_INUSE) {
@@ -1432,16 +1435,30 @@ static void nv_mac_reset(struct net_device *dev)
1432{ 1435{
1433 struct fe_priv *np = netdev_priv(dev); 1436 struct fe_priv *np = netdev_priv(dev);
1434 u8 __iomem *base = get_hwbase(dev); 1437 u8 __iomem *base = get_hwbase(dev);
1438 u32 temp1, temp2, temp3;
1435 1439
1436 dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name); 1440 dprintk(KERN_DEBUG "%s: nv_mac_reset\n", dev->name);
1441
1437 writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl); 1442 writel(NVREG_TXRXCTL_BIT2 | NVREG_TXRXCTL_RESET | np->txrxctl_bits, base + NvRegTxRxControl);
1438 pci_push(base); 1443 pci_push(base);
1444
1445 /* save registers since they will be cleared on reset */
1446 temp1 = readl(base + NvRegMacAddrA);
1447 temp2 = readl(base + NvRegMacAddrB);
1448 temp3 = readl(base + NvRegTransmitPoll);
1449
1439 writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset); 1450 writel(NVREG_MAC_RESET_ASSERT, base + NvRegMacReset);
1440 pci_push(base); 1451 pci_push(base);
1441 udelay(NV_MAC_RESET_DELAY); 1452 udelay(NV_MAC_RESET_DELAY);
1442 writel(0, base + NvRegMacReset); 1453 writel(0, base + NvRegMacReset);
1443 pci_push(base); 1454 pci_push(base);
1444 udelay(NV_MAC_RESET_DELAY); 1455 udelay(NV_MAC_RESET_DELAY);
1456
1457 /* restore saved registers */
1458 writel(temp1, base + NvRegMacAddrA);
1459 writel(temp2, base + NvRegMacAddrB);
1460 writel(temp3, base + NvRegTransmitPoll);
1461
1445 writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl); 1462 writel(NVREG_TXRXCTL_BIT2 | np->txrxctl_bits, base + NvRegTxRxControl);
1446 pci_push(base); 1463 pci_push(base);
1447} 1464}
@@ -2767,6 +2784,7 @@ static int nv_update_linkspeed(struct net_device *dev)
2767 int mii_status; 2784 int mii_status;
2768 int retval = 0; 2785 int retval = 0;
2769 u32 control_1000, status_1000, phyreg, pause_flags, txreg; 2786 u32 control_1000, status_1000, phyreg, pause_flags, txreg;
2787 u32 txrxFlags = 0;
2770 2788
2771 /* BMSR_LSTATUS is latched, read it twice: 2789 /* BMSR_LSTATUS is latched, read it twice:
2772 * we want the current value. 2790 * we want the current value.
@@ -2862,6 +2880,16 @@ set_speed:
2862 np->duplex = newdup; 2880 np->duplex = newdup;
2863 np->linkspeed = newls; 2881 np->linkspeed = newls;
2864 2882
2883 /* The transmitter and receiver must be restarted for safe update */
2884 if (readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START) {
2885 txrxFlags |= NV_RESTART_TX;
2886 nv_stop_tx(dev);
2887 }
2888 if (readl(base + NvRegReceiverControl) & NVREG_RCVCTL_START) {
2889 txrxFlags |= NV_RESTART_RX;
2890 nv_stop_rx(dev);
2891 }
2892
2865 if (np->gigabit == PHY_GIGABIT) { 2893 if (np->gigabit == PHY_GIGABIT) {
2866 phyreg = readl(base + NvRegRandomSeed); 2894 phyreg = readl(base + NvRegRandomSeed);
2867 phyreg &= ~(0x3FF00); 2895 phyreg &= ~(0x3FF00);
@@ -2950,6 +2978,11 @@ set_speed:
2950 } 2978 }
2951 nv_update_pause(dev, pause_flags); 2979 nv_update_pause(dev, pause_flags);
2952 2980
2981 if (txrxFlags & NV_RESTART_TX)
2982 nv_start_tx(dev);
2983 if (txrxFlags & NV_RESTART_RX)
2984 nv_start_rx(dev);
2985
2953 return retval; 2986 return retval;
2954} 2987}
2955 2988
@@ -2976,7 +3009,7 @@ static void nv_link_irq(struct net_device *dev)
2976 u32 miistat; 3009 u32 miistat;
2977 3010
2978 miistat = readl(base + NvRegMIIStatus); 3011 miistat = readl(base + NvRegMIIStatus);
2979 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); 3012 writel(NVREG_MIISTAT_LINKCHANGE, base + NvRegMIIStatus);
2980 dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat); 3013 dprintk(KERN_INFO "%s: link change irq, status 0x%x.\n", dev->name, miistat);
2981 3014
2982 if (miistat & (NVREG_MIISTAT_LINKCHANGE)) 3015 if (miistat & (NVREG_MIISTAT_LINKCHANGE))
@@ -4851,7 +4884,7 @@ static int nv_open(struct net_device *dev)
4851 4884
4852 writel(0, base + NvRegMIIMask); 4885 writel(0, base + NvRegMIIMask);
4853 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); 4886 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
4854 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); 4887 writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
4855 4888
4856 writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1); 4889 writel(NVREG_MISC1_FORCE | NVREG_MISC1_HD, base + NvRegMisc1);
4857 writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus); 4890 writel(readl(base + NvRegTransmitterStatus), base + NvRegTransmitterStatus);
@@ -4889,7 +4922,7 @@ static int nv_open(struct net_device *dev)
4889 4922
4890 nv_disable_hw_interrupts(dev, np->irqmask); 4923 nv_disable_hw_interrupts(dev, np->irqmask);
4891 pci_push(base); 4924 pci_push(base);
4892 writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); 4925 writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
4893 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); 4926 writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
4894 pci_push(base); 4927 pci_push(base);
4895 4928
@@ -4912,7 +4945,7 @@ static int nv_open(struct net_device *dev)
4912 { 4945 {
4913 u32 miistat; 4946 u32 miistat;
4914 miistat = readl(base + NvRegMIIStatus); 4947 miistat = readl(base + NvRegMIIStatus);
4915 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); 4948 writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
4916 dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat); 4949 dprintk(KERN_INFO "startup: got 0x%08x.\n", miistat);
4917 } 4950 }
4918 /* set linkspeed to invalid value, thus force nv_update_linkspeed 4951 /* set linkspeed to invalid value, thus force nv_update_linkspeed
@@ -5280,7 +5313,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
5280 phystate &= ~NVREG_ADAPTCTL_RUNNING; 5313 phystate &= ~NVREG_ADAPTCTL_RUNNING;
5281 writel(phystate, base + NvRegAdapterControl); 5314 writel(phystate, base + NvRegAdapterControl);
5282 } 5315 }
5283 writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); 5316 writel(NVREG_MIISTAT_MASK_ALL, base + NvRegMIIStatus);
5284 5317
5285 if (id->driver_data & DEV_HAS_MGMT_UNIT) { 5318 if (id->driver_data & DEV_HAS_MGMT_UNIT) {
5286 /* management unit running on the mac? */ 5319 /* management unit running on the mac? */