diff options
| author | David S. Miller <davem@davemloft.net> | 2008-02-06 06:52:44 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-02-06 06:52:44 -0500 |
| commit | 655d2ce073f5927194dbc28d2bd3c062a4a3caac (patch) | |
| tree | 9fa289764e2b3cd8dbdc6d11299f0f16b93414b6 /drivers/net/forcedeth.c | |
| parent | 9c1ca6e68a5d8d58776833b6496c0656a10be50c (diff) | |
| parent | 370076d932ff56a02b9c5328729a69d432cd4b32 (diff) | |
Merge branch 'upstream-davem' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
Diffstat (limited to 'drivers/net/forcedeth.c')
| -rw-r--r-- | drivers/net/forcedeth.c | 49 |
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 */ |
| 628 | struct nv_ethtool_str { | 631 | struct 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? */ |
