diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 290 |
1 files changed, 269 insertions, 21 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index c5ed635bce36..439f41338291 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -110,6 +110,8 @@ | |||
110 | * 0.55: 22 Mar 2006: Add flow control (pause frame). | 110 | * 0.55: 22 Mar 2006: Add flow control (pause frame). |
111 | * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. | 111 | * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. |
112 | * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. | 112 | * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. |
113 | * 0.58: 30 Oct 2006: Added support for sideband management unit. | ||
114 | * 0.59: 30 Oct 2006: Added support for recoverable error. | ||
113 | * | 115 | * |
114 | * Known bugs: | 116 | * Known bugs: |
115 | * We suspect that on some hardware no TX done interrupts are generated. | 117 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -126,7 +128,7 @@ | |||
126 | #else | 128 | #else |
127 | #define DRIVERNAPI | 129 | #define DRIVERNAPI |
128 | #endif | 130 | #endif |
129 | #define FORCEDETH_VERSION "0.57" | 131 | #define FORCEDETH_VERSION "0.59" |
130 | #define DRV_NAME "forcedeth" | 132 | #define DRV_NAME "forcedeth" |
131 | 133 | ||
132 | #include <linux/module.h> | 134 | #include <linux/module.h> |
@@ -174,11 +176,12 @@ | |||
174 | #define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ | 176 | #define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ |
175 | #define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */ | 177 | #define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */ |
176 | #define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */ | 178 | #define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */ |
179 | #define DEV_HAS_MGMT_UNIT 0x1000 /* device supports management unit */ | ||
177 | 180 | ||
178 | enum { | 181 | enum { |
179 | NvRegIrqStatus = 0x000, | 182 | NvRegIrqStatus = 0x000, |
180 | #define NVREG_IRQSTAT_MIIEVENT 0x040 | 183 | #define NVREG_IRQSTAT_MIIEVENT 0x040 |
181 | #define NVREG_IRQSTAT_MASK 0x1ff | 184 | #define NVREG_IRQSTAT_MASK 0x81ff |
182 | NvRegIrqMask = 0x004, | 185 | NvRegIrqMask = 0x004, |
183 | #define NVREG_IRQ_RX_ERROR 0x0001 | 186 | #define NVREG_IRQ_RX_ERROR 0x0001 |
184 | #define NVREG_IRQ_RX 0x0002 | 187 | #define NVREG_IRQ_RX 0x0002 |
@@ -189,15 +192,16 @@ enum { | |||
189 | #define NVREG_IRQ_LINK 0x0040 | 192 | #define NVREG_IRQ_LINK 0x0040 |
190 | #define NVREG_IRQ_RX_FORCED 0x0080 | 193 | #define NVREG_IRQ_RX_FORCED 0x0080 |
191 | #define NVREG_IRQ_TX_FORCED 0x0100 | 194 | #define NVREG_IRQ_TX_FORCED 0x0100 |
195 | #define NVREG_IRQ_RECOVER_ERROR 0x8000 | ||
192 | #define NVREG_IRQMASK_THROUGHPUT 0x00df | 196 | #define NVREG_IRQMASK_THROUGHPUT 0x00df |
193 | #define NVREG_IRQMASK_CPU 0x0040 | 197 | #define NVREG_IRQMASK_CPU 0x0040 |
194 | #define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED) | 198 | #define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED) |
195 | #define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED) | 199 | #define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED) |
196 | #define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK) | 200 | #define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR) |
197 | 201 | ||
198 | #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ | 202 | #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ |
199 | NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \ | 203 | NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \ |
200 | NVREG_IRQ_TX_FORCED)) | 204 | NVREG_IRQ_TX_FORCED|NVREG_IRQ_RECOVER_ERROR)) |
201 | 205 | ||
202 | NvRegUnknownSetupReg6 = 0x008, | 206 | NvRegUnknownSetupReg6 = 0x008, |
203 | #define NVREG_UNKSETUP6_VAL 3 | 207 | #define NVREG_UNKSETUP6_VAL 3 |
@@ -222,6 +226,15 @@ enum { | |||
222 | #define NVREG_MAC_RESET_ASSERT 0x0F3 | 226 | #define NVREG_MAC_RESET_ASSERT 0x0F3 |
223 | NvRegTransmitterControl = 0x084, | 227 | NvRegTransmitterControl = 0x084, |
224 | #define NVREG_XMITCTL_START 0x01 | 228 | #define NVREG_XMITCTL_START 0x01 |
229 | #define NVREG_XMITCTL_MGMT_ST 0x40000000 | ||
230 | #define NVREG_XMITCTL_SYNC_MASK 0x000f0000 | ||
231 | #define NVREG_XMITCTL_SYNC_NOT_READY 0x0 | ||
232 | #define NVREG_XMITCTL_SYNC_PHY_INIT 0x00040000 | ||
233 | #define NVREG_XMITCTL_MGMT_SEMA_MASK 0x00000f00 | ||
234 | #define NVREG_XMITCTL_MGMT_SEMA_FREE 0x0 | ||
235 | #define NVREG_XMITCTL_HOST_SEMA_MASK 0x0000f000 | ||
236 | #define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000 | ||
237 | #define NVREG_XMITCTL_HOST_LOADED 0x00004000 | ||
225 | NvRegTransmitterStatus = 0x088, | 238 | NvRegTransmitterStatus = 0x088, |
226 | #define NVREG_XMITSTAT_BUSY 0x01 | 239 | #define NVREG_XMITSTAT_BUSY 0x01 |
227 | 240 | ||
@@ -304,8 +317,8 @@ enum { | |||
304 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 | 317 | #define NVREG_MIISTAT_LINKCHANGE 0x0008 |
305 | #define NVREG_MIISTAT_MASK 0x000f | 318 | #define NVREG_MIISTAT_MASK 0x000f |
306 | #define NVREG_MIISTAT_MASK2 0x000f | 319 | #define NVREG_MIISTAT_MASK2 0x000f |
307 | NvRegUnknownSetupReg4 = 0x184, | 320 | NvRegMIIMask = 0x184, |
308 | #define NVREG_UNKSETUP4_VAL 8 | 321 | #define NVREG_MII_LINKCHANGE 0x0008 |
309 | 322 | ||
310 | NvRegAdapterControl = 0x188, | 323 | NvRegAdapterControl = 0x188, |
311 | #define NVREG_ADAPTCTL_START 0x02 | 324 | #define NVREG_ADAPTCTL_START 0x02 |
@@ -707,6 +720,7 @@ struct fe_priv { | |||
707 | unsigned int phy_model; | 720 | unsigned int phy_model; |
708 | u16 gigabit; | 721 | u16 gigabit; |
709 | int intr_test; | 722 | int intr_test; |
723 | int recover_error; | ||
710 | 724 | ||
711 | /* General data: RO fields */ | 725 | /* General data: RO fields */ |
712 | dma_addr_t ring_addr; | 726 | dma_addr_t ring_addr; |
@@ -719,6 +733,7 @@ struct fe_priv { | |||
719 | u32 driver_data; | 733 | u32 driver_data; |
720 | u32 register_size; | 734 | u32 register_size; |
721 | int rx_csum; | 735 | int rx_csum; |
736 | u32 mac_in_use; | ||
722 | 737 | ||
723 | void __iomem *base; | 738 | void __iomem *base; |
724 | 739 | ||
@@ -2443,6 +2458,23 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
2443 | printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", | 2458 | printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", |
2444 | dev->name, events); | 2459 | dev->name, events); |
2445 | } | 2460 | } |
2461 | if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) { | ||
2462 | spin_lock(&np->lock); | ||
2463 | /* disable interrupts on the nic */ | ||
2464 | if (!(np->msi_flags & NV_MSI_X_ENABLED)) | ||
2465 | writel(0, base + NvRegIrqMask); | ||
2466 | else | ||
2467 | writel(np->irqmask, base + NvRegIrqMask); | ||
2468 | pci_push(base); | ||
2469 | |||
2470 | if (!np->in_shutdown) { | ||
2471 | np->nic_poll_irq = np->irqmask; | ||
2472 | np->recover_error = 1; | ||
2473 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | ||
2474 | } | ||
2475 | spin_unlock(&np->lock); | ||
2476 | break; | ||
2477 | } | ||
2446 | #ifdef CONFIG_FORCEDETH_NAPI | 2478 | #ifdef CONFIG_FORCEDETH_NAPI |
2447 | if (events & NVREG_IRQ_RX_ALL) { | 2479 | if (events & NVREG_IRQ_RX_ALL) { |
2448 | netif_rx_schedule(dev); | 2480 | netif_rx_schedule(dev); |
@@ -2673,6 +2705,20 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) | |||
2673 | spin_unlock_irqrestore(&np->lock, flags); | 2705 | spin_unlock_irqrestore(&np->lock, flags); |
2674 | np->link_timeout = jiffies + LINK_TIMEOUT; | 2706 | np->link_timeout = jiffies + LINK_TIMEOUT; |
2675 | } | 2707 | } |
2708 | if (events & NVREG_IRQ_RECOVER_ERROR) { | ||
2709 | spin_lock_irq(&np->lock); | ||
2710 | /* disable interrupts on the nic */ | ||
2711 | writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); | ||
2712 | pci_push(base); | ||
2713 | |||
2714 | if (!np->in_shutdown) { | ||
2715 | np->nic_poll_irq |= NVREG_IRQ_OTHER; | ||
2716 | np->recover_error = 1; | ||
2717 | mod_timer(&np->nic_poll, jiffies + POLL_WAIT); | ||
2718 | } | ||
2719 | spin_unlock_irq(&np->lock); | ||
2720 | break; | ||
2721 | } | ||
2676 | if (events & (NVREG_IRQ_UNKNOWN)) { | 2722 | if (events & (NVREG_IRQ_UNKNOWN)) { |
2677 | printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", | 2723 | printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", |
2678 | dev->name, events); | 2724 | dev->name, events); |
@@ -2902,6 +2948,42 @@ static void nv_do_nic_poll(unsigned long data) | |||
2902 | } | 2948 | } |
2903 | np->nic_poll_irq = 0; | 2949 | np->nic_poll_irq = 0; |
2904 | 2950 | ||
2951 | if (np->recover_error) { | ||
2952 | np->recover_error = 0; | ||
2953 | printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); | ||
2954 | if (netif_running(dev)) { | ||
2955 | netif_tx_lock_bh(dev); | ||
2956 | spin_lock(&np->lock); | ||
2957 | /* stop engines */ | ||
2958 | nv_stop_rx(dev); | ||
2959 | nv_stop_tx(dev); | ||
2960 | nv_txrx_reset(dev); | ||
2961 | /* drain rx queue */ | ||
2962 | nv_drain_rx(dev); | ||
2963 | nv_drain_tx(dev); | ||
2964 | /* reinit driver view of the rx queue */ | ||
2965 | set_bufsize(dev); | ||
2966 | if (nv_init_ring(dev)) { | ||
2967 | if (!np->in_shutdown) | ||
2968 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | ||
2969 | } | ||
2970 | /* reinit nic view of the rx queue */ | ||
2971 | writel(np->rx_buf_sz, base + NvRegOffloadConfig); | ||
2972 | setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); | ||
2973 | writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), | ||
2974 | base + NvRegRingSizes); | ||
2975 | pci_push(base); | ||
2976 | writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); | ||
2977 | pci_push(base); | ||
2978 | |||
2979 | /* restart rx engine */ | ||
2980 | nv_start_rx(dev); | ||
2981 | nv_start_tx(dev); | ||
2982 | spin_unlock(&np->lock); | ||
2983 | netif_tx_unlock_bh(dev); | ||
2984 | } | ||
2985 | } | ||
2986 | |||
2905 | /* FIXME: Do we need synchronize_irq(dev->irq) here? */ | 2987 | /* FIXME: Do we need synchronize_irq(dev->irq) here? */ |
2906 | 2988 | ||
2907 | writel(mask, base + NvRegIrqMask); | 2989 | writel(mask, base + NvRegIrqMask); |
@@ -4030,6 +4112,54 @@ static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) | |||
4030 | /* nothing to do */ | 4112 | /* nothing to do */ |
4031 | }; | 4113 | }; |
4032 | 4114 | ||
4115 | /* The mgmt unit and driver use a semaphore to access the phy during init */ | ||
4116 | static int nv_mgmt_acquire_sema(struct net_device *dev) | ||
4117 | { | ||
4118 | u8 __iomem *base = get_hwbase(dev); | ||
4119 | int i; | ||
4120 | u32 tx_ctrl, mgmt_sema; | ||
4121 | |||
4122 | for (i = 0; i < 10; i++) { | ||
4123 | mgmt_sema = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_SEMA_MASK; | ||
4124 | if (mgmt_sema == NVREG_XMITCTL_MGMT_SEMA_FREE) | ||
4125 | break; | ||
4126 | msleep(500); | ||
4127 | } | ||
4128 | |||
4129 | if (mgmt_sema != NVREG_XMITCTL_MGMT_SEMA_FREE) | ||
4130 | return 0; | ||
4131 | |||
4132 | for (i = 0; i < 2; i++) { | ||
4133 | tx_ctrl = readl(base + NvRegTransmitterControl); | ||
4134 | tx_ctrl |= NVREG_XMITCTL_HOST_SEMA_ACQ; | ||
4135 | writel(tx_ctrl, base + NvRegTransmitterControl); | ||
4136 | |||
4137 | /* verify that semaphore was acquired */ | ||
4138 | tx_ctrl = readl(base + NvRegTransmitterControl); | ||
4139 | if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) && | ||
4140 | ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) | ||
4141 | return 1; | ||
4142 | else | ||
4143 | udelay(50); | ||
4144 | } | ||
4145 | |||
4146 | return 0; | ||
4147 | } | ||
4148 | |||
4149 | /* Indicate to mgmt unit whether driver is loaded or not */ | ||
4150 | static void nv_mgmt_driver_loaded(struct net_device *dev, int loaded) | ||
4151 | { | ||
4152 | u8 __iomem *base = get_hwbase(dev); | ||
4153 | u32 tx_ctrl; | ||
4154 | |||
4155 | tx_ctrl = readl(base + NvRegTransmitterControl); | ||
4156 | if (loaded) | ||
4157 | tx_ctrl |= NVREG_XMITCTL_HOST_LOADED; | ||
4158 | else | ||
4159 | tx_ctrl &= ~NVREG_XMITCTL_HOST_LOADED; | ||
4160 | writel(tx_ctrl, base + NvRegTransmitterControl); | ||
4161 | } | ||
4162 | |||
4033 | static int nv_open(struct net_device *dev) | 4163 | static int nv_open(struct net_device *dev) |
4034 | { | 4164 | { |
4035 | struct fe_priv *np = netdev_priv(dev); | 4165 | struct fe_priv *np = netdev_priv(dev); |
@@ -4085,7 +4215,7 @@ static int nv_open(struct net_device *dev) | |||
4085 | NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, | 4215 | NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, |
4086 | KERN_INFO "open: SetupReg5, Bit 31 remained off\n"); | 4216 | KERN_INFO "open: SetupReg5, Bit 31 remained off\n"); |
4087 | 4217 | ||
4088 | writel(0, base + NvRegUnknownSetupReg4); | 4218 | writel(0, base + NvRegMIIMask); |
4089 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); | 4219 | writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); |
4090 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); | 4220 | writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); |
4091 | 4221 | ||
@@ -4111,7 +4241,7 @@ static int nv_open(struct net_device *dev) | |||
4111 | writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, | 4241 | writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, |
4112 | base + NvRegAdapterControl); | 4242 | base + NvRegAdapterControl); |
4113 | writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed); | 4243 | writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed); |
4114 | writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4); | 4244 | writel(NVREG_MII_LINKCHANGE, base + NvRegMIIMask); |
4115 | if (np->wolenabled) | 4245 | if (np->wolenabled) |
4116 | writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags); | 4246 | writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags); |
4117 | 4247 | ||
@@ -4230,6 +4360,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4230 | u8 __iomem *base; | 4360 | u8 __iomem *base; |
4231 | int err, i; | 4361 | int err, i; |
4232 | u32 powerstate, txreg; | 4362 | u32 powerstate, txreg; |
4363 | u32 phystate_orig = 0, phystate; | ||
4364 | int phyinitialized = 0; | ||
4233 | 4365 | ||
4234 | dev = alloc_etherdev(sizeof(struct fe_priv)); | 4366 | dev = alloc_etherdev(sizeof(struct fe_priv)); |
4235 | err = -ENOMEM; | 4367 | err = -ENOMEM; |
@@ -4514,6 +4646,48 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4514 | np->need_linktimer = 0; | 4646 | np->need_linktimer = 0; |
4515 | } | 4647 | } |
4516 | 4648 | ||
4649 | /* clear phy state and temporarily halt phy interrupts */ | ||
4650 | writel(0, base + NvRegMIIMask); | ||
4651 | phystate = readl(base + NvRegAdapterControl); | ||
4652 | if (phystate & NVREG_ADAPTCTL_RUNNING) { | ||
4653 | phystate_orig = 1; | ||
4654 | phystate &= ~NVREG_ADAPTCTL_RUNNING; | ||
4655 | writel(phystate, base + NvRegAdapterControl); | ||
4656 | } | ||
4657 | writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); | ||
4658 | |||
4659 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { | ||
4660 | writel(0x1, base + 0x204); pci_push(base); | ||
4661 | msleep(500); | ||
4662 | /* management unit running on the mac? */ | ||
4663 | np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; | ||
4664 | if (np->mac_in_use) { | ||
4665 | u32 mgmt_sync; | ||
4666 | /* management unit setup the phy already? */ | ||
4667 | mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK; | ||
4668 | if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) { | ||
4669 | if (!nv_mgmt_acquire_sema(dev)) { | ||
4670 | for (i = 0; i < 5000; i++) { | ||
4671 | msleep(1); | ||
4672 | mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK; | ||
4673 | if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) | ||
4674 | continue; | ||
4675 | if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) | ||
4676 | phyinitialized = 1; | ||
4677 | break; | ||
4678 | } | ||
4679 | } else { | ||
4680 | /* we need to init the phy */ | ||
4681 | } | ||
4682 | } else if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) { | ||
4683 | /* phy is inited by SMU */ | ||
4684 | phyinitialized = 1; | ||
4685 | } else { | ||
4686 | /* we need to init the phy */ | ||
4687 | } | ||
4688 | } | ||
4689 | } | ||
4690 | |||
4517 | /* find a suitable phy */ | 4691 | /* find a suitable phy */ |
4518 | for (i = 1; i <= 32; i++) { | 4692 | for (i = 1; i <= 32; i++) { |
4519 | int id1, id2; | 4693 | int id1, id2; |
@@ -4545,8 +4719,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4545 | goto out_error; | 4719 | goto out_error; |
4546 | } | 4720 | } |
4547 | 4721 | ||
4548 | /* reset it */ | 4722 | if (!phyinitialized) { |
4549 | phy_init(dev); | 4723 | /* reset it */ |
4724 | phy_init(dev); | ||
4725 | } | ||
4726 | |||
4727 | if (id->driver_data & DEV_HAS_MGMT_UNIT) { | ||
4728 | nv_mgmt_driver_loaded(dev, 1); | ||
4729 | } | ||
4550 | 4730 | ||
4551 | /* set default link speed settings */ | 4731 | /* set default link speed settings */ |
4552 | np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; | 4732 | np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; |
@@ -4565,6 +4745,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
4565 | return 0; | 4745 | return 0; |
4566 | 4746 | ||
4567 | out_error: | 4747 | out_error: |
4748 | if (phystate_orig) | ||
4749 | writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl); | ||
4750 | if (np->mac_in_use) | ||
4751 | nv_mgmt_driver_loaded(dev, 0); | ||
4568 | pci_set_drvdata(pci_dev, NULL); | 4752 | pci_set_drvdata(pci_dev, NULL); |
4569 | out_freering: | 4753 | out_freering: |
4570 | free_rings(dev); | 4754 | free_rings(dev); |
@@ -4594,6 +4778,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) | |||
4594 | writel(np->orig_mac[0], base + NvRegMacAddrA); | 4778 | writel(np->orig_mac[0], base + NvRegMacAddrA); |
4595 | writel(np->orig_mac[1], base + NvRegMacAddrB); | 4779 | writel(np->orig_mac[1], base + NvRegMacAddrB); |
4596 | 4780 | ||
4781 | if (np->mac_in_use) | ||
4782 | nv_mgmt_driver_loaded(dev, 0); | ||
4783 | |||
4597 | /* free all structures */ | 4784 | /* free all structures */ |
4598 | free_rings(dev); | 4785 | free_rings(dev); |
4599 | iounmap(get_hwbase(dev)); | 4786 | iounmap(get_hwbase(dev)); |
@@ -4603,6 +4790,50 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) | |||
4603 | pci_set_drvdata(pci_dev, NULL); | 4790 | pci_set_drvdata(pci_dev, NULL); |
4604 | } | 4791 | } |
4605 | 4792 | ||
4793 | #ifdef CONFIG_PM | ||
4794 | static int nv_suspend(struct pci_dev *pdev, pm_message_t state) | ||
4795 | { | ||
4796 | struct net_device *dev = pci_get_drvdata(pdev); | ||
4797 | struct fe_priv *np = netdev_priv(dev); | ||
4798 | |||
4799 | if (!netif_running(dev)) | ||
4800 | goto out; | ||
4801 | |||
4802 | netif_device_detach(dev); | ||
4803 | |||
4804 | // Gross. | ||
4805 | nv_close(dev); | ||
4806 | |||
4807 | pci_save_state(pdev); | ||
4808 | pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); | ||
4809 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
4810 | out: | ||
4811 | return 0; | ||
4812 | } | ||
4813 | |||
4814 | static int nv_resume(struct pci_dev *pdev) | ||
4815 | { | ||
4816 | struct net_device *dev = pci_get_drvdata(pdev); | ||
4817 | int rc = 0; | ||
4818 | |||
4819 | if (!netif_running(dev)) | ||
4820 | goto out; | ||
4821 | |||
4822 | netif_device_attach(dev); | ||
4823 | |||
4824 | pci_set_power_state(pdev, PCI_D0); | ||
4825 | pci_restore_state(pdev); | ||
4826 | pci_enable_wake(pdev, PCI_D0, 0); | ||
4827 | |||
4828 | rc = nv_open(dev); | ||
4829 | out: | ||
4830 | return rc; | ||
4831 | } | ||
4832 | #else | ||
4833 | #define nv_suspend NULL | ||
4834 | #define nv_resume NULL | ||
4835 | #endif /* CONFIG_PM */ | ||
4836 | |||
4606 | static struct pci_device_id pci_tbl[] = { | 4837 | static struct pci_device_id pci_tbl[] = { |
4607 | { /* nForce Ethernet Controller */ | 4838 | { /* nForce Ethernet Controller */ |
4608 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1), | 4839 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1), |
@@ -4658,43 +4889,59 @@ static struct pci_device_id pci_tbl[] = { | |||
4658 | }, | 4889 | }, |
4659 | { /* MCP55 Ethernet Controller */ | 4890 | { /* MCP55 Ethernet Controller */ |
4660 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), | 4891 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), |
4661 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4892 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4662 | }, | 4893 | }, |
4663 | { /* MCP55 Ethernet Controller */ | 4894 | { /* MCP55 Ethernet Controller */ |
4664 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), | 4895 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), |
4665 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4896 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4666 | }, | 4897 | }, |
4667 | { /* MCP61 Ethernet Controller */ | 4898 | { /* MCP61 Ethernet Controller */ |
4668 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), | 4899 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), |
4669 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4900 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4670 | }, | 4901 | }, |
4671 | { /* MCP61 Ethernet Controller */ | 4902 | { /* MCP61 Ethernet Controller */ |
4672 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), | 4903 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), |
4673 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4904 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4674 | }, | 4905 | }, |
4675 | { /* MCP61 Ethernet Controller */ | 4906 | { /* MCP61 Ethernet Controller */ |
4676 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), | 4907 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), |
4677 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4908 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4678 | }, | 4909 | }, |
4679 | { /* MCP61 Ethernet Controller */ | 4910 | { /* MCP61 Ethernet Controller */ |
4680 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), | 4911 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), |
4681 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4912 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4682 | }, | 4913 | }, |
4683 | { /* MCP65 Ethernet Controller */ | 4914 | { /* MCP65 Ethernet Controller */ |
4684 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), | 4915 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), |
4685 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4916 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4686 | }, | 4917 | }, |
4687 | { /* MCP65 Ethernet Controller */ | 4918 | { /* MCP65 Ethernet Controller */ |
4688 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), | 4919 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), |
4689 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4920 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4690 | }, | 4921 | }, |
4691 | { /* MCP65 Ethernet Controller */ | 4922 | { /* MCP65 Ethernet Controller */ |
4692 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), | 4923 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), |
4693 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4924 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4694 | }, | 4925 | }, |
4695 | { /* MCP65 Ethernet Controller */ | 4926 | { /* MCP65 Ethernet Controller */ |
4696 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), | 4927 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), |
4697 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, | 4928 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, |
4929 | }, | ||
4930 | { /* MCP67 Ethernet Controller */ | ||
4931 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), | ||
4932 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, | ||
4933 | }, | ||
4934 | { /* MCP67 Ethernet Controller */ | ||
4935 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), | ||
4936 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, | ||
4937 | }, | ||
4938 | { /* MCP67 Ethernet Controller */ | ||
4939 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), | ||
4940 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, | ||
4941 | }, | ||
4942 | { /* MCP67 Ethernet Controller */ | ||
4943 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), | ||
4944 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, | ||
4698 | }, | 4945 | }, |
4699 | {0,}, | 4946 | {0,}, |
4700 | }; | 4947 | }; |
@@ -4704,9 +4951,10 @@ static struct pci_driver driver = { | |||
4704 | .id_table = pci_tbl, | 4951 | .id_table = pci_tbl, |
4705 | .probe = nv_probe, | 4952 | .probe = nv_probe, |
4706 | .remove = __devexit_p(nv_remove), | 4953 | .remove = __devexit_p(nv_remove), |
4954 | .suspend = nv_suspend, | ||
4955 | .resume = nv_resume, | ||
4707 | }; | 4956 | }; |
4708 | 4957 | ||
4709 | |||
4710 | static int __init init_nic(void) | 4958 | static int __init init_nic(void) |
4711 | { | 4959 | { |
4712 | printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION); | 4960 | printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION); |