diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 231 |
1 files changed, 138 insertions, 93 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 22aec6ed80f5..525624fc03b4 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -80,7 +80,7 @@ | |||
80 | * into nv_close, otherwise reenabling for wol can | 80 | * into nv_close, otherwise reenabling for wol can |
81 | * cause DMA to kfree'd memory. | 81 | * cause DMA to kfree'd memory. |
82 | * 0.31: 14 Nov 2004: ethtool support for getting/setting link | 82 | * 0.31: 14 Nov 2004: ethtool support for getting/setting link |
83 | * capabilities. | 83 | * capabilities. |
84 | * 0.32: 16 Apr 2005: RX_ERROR4 handling added. | 84 | * 0.32: 16 Apr 2005: RX_ERROR4 handling added. |
85 | * 0.33: 16 May 2005: Support for MCP51 added. | 85 | * 0.33: 16 May 2005: Support for MCP51 added. |
86 | * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics. | 86 | * 0.34: 18 Jun 2005: Add DEV_NEED_LINKTIMER to all nForce nics. |
@@ -89,14 +89,17 @@ | |||
89 | * 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list | 89 | * 0.37: 10 Jul 2005: Additional ethtool support, cleanup of pci id list |
90 | * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of | 90 | * 0.38: 16 Jul 2005: tx irq rewrite: Use global flags instead of |
91 | * per-packet flags. | 91 | * per-packet flags. |
92 | * 0.39: 18 Jul 2005: Add 64bit descriptor support. | 92 | * 0.39: 18 Jul 2005: Add 64bit descriptor support. |
93 | * 0.40: 19 Jul 2005: Add support for mac address change. | 93 | * 0.40: 19 Jul 2005: Add support for mac address change. |
94 | * 0.41: 30 Jul 2005: Write back original MAC in nv_close instead | 94 | * 0.41: 30 Jul 2005: Write back original MAC in nv_close instead |
95 | * of nv_remove | 95 | * of nv_remove |
96 | * 0.42: 06 Aug 2005: Fix lack of link speed initialization | 96 | * 0.42: 06 Aug 2005: Fix lack of link speed initialization |
97 | * in the second (and later) nv_open call | 97 | * in the second (and later) nv_open call |
98 | * 0.43: 10 Aug 2005: Add support for tx checksum. | 98 | * 0.43: 10 Aug 2005: Add support for tx checksum. |
99 | * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation. | 99 | * 0.44: 20 Aug 2005: Add support for scatter gather and segmentation. |
100 | * 0.45: 18 Sep 2005: Remove nv_stop/start_rx from every link check | ||
101 | * 0.46: 20 Oct 2005: Add irq optimization modes. | ||
102 | * 0.47: 26 Oct 2005: Add phyaddr 0 in phy scan. | ||
100 | * | 103 | * |
101 | * Known bugs: | 104 | * Known bugs: |
102 | * We suspect that on some hardware no TX done interrupts are generated. | 105 | * We suspect that on some hardware no TX done interrupts are generated. |
@@ -108,7 +111,7 @@ | |||
108 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few | 111 | * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few |
109 | * superfluous timer interrupts from the nic. | 112 | * superfluous timer interrupts from the nic. |
110 | */ | 113 | */ |
111 | #define FORCEDETH_VERSION "0.44" | 114 | #define FORCEDETH_VERSION "0.47" |
112 | #define DRV_NAME "forcedeth" | 115 | #define DRV_NAME "forcedeth" |
113 | 116 | ||
114 | #include <linux/module.h> | 117 | #include <linux/module.h> |
@@ -163,7 +166,8 @@ enum { | |||
163 | #define NVREG_IRQ_LINK 0x0040 | 166 | #define NVREG_IRQ_LINK 0x0040 |
164 | #define NVREG_IRQ_TX_ERROR 0x0080 | 167 | #define NVREG_IRQ_TX_ERROR 0x0080 |
165 | #define NVREG_IRQ_TX1 0x0100 | 168 | #define NVREG_IRQ_TX1 0x0100 |
166 | #define NVREG_IRQMASK_WANTED 0x00df | 169 | #define NVREG_IRQMASK_THROUGHPUT 0x00df |
170 | #define NVREG_IRQMASK_CPU 0x0040 | ||
167 | 171 | ||
168 | #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ | 172 | #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ |
169 | NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \ | 173 | NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_TX_ERROR| \ |
@@ -177,7 +181,8 @@ enum { | |||
177 | * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms | 181 | * NVREG_POLL_DEFAULT=97 would result in an interval length of 1 ms |
178 | */ | 182 | */ |
179 | NvRegPollingInterval = 0x00c, | 183 | NvRegPollingInterval = 0x00c, |
180 | #define NVREG_POLL_DEFAULT 970 | 184 | #define NVREG_POLL_DEFAULT_THROUGHPUT 970 |
185 | #define NVREG_POLL_DEFAULT_CPU 13 | ||
181 | NvRegMisc1 = 0x080, | 186 | NvRegMisc1 = 0x080, |
182 | #define NVREG_MISC1_HD 0x02 | 187 | #define NVREG_MISC1_HD 0x02 |
183 | #define NVREG_MISC1_FORCE 0x3b0f3c | 188 | #define NVREG_MISC1_FORCE 0x3b0f3c |
@@ -538,6 +543,25 @@ struct fe_priv { | |||
538 | */ | 543 | */ |
539 | static int max_interrupt_work = 5; | 544 | static int max_interrupt_work = 5; |
540 | 545 | ||
546 | /* | ||
547 | * Optimization can be either throuput mode or cpu mode | ||
548 | * | ||
549 | * Throughput Mode: Every tx and rx packet will generate an interrupt. | ||
550 | * CPU Mode: Interrupts are controlled by a timer. | ||
551 | */ | ||
552 | #define NV_OPTIMIZATION_MODE_THROUGHPUT 0 | ||
553 | #define NV_OPTIMIZATION_MODE_CPU 1 | ||
554 | static int optimization_mode = NV_OPTIMIZATION_MODE_THROUGHPUT; | ||
555 | |||
556 | /* | ||
557 | * Poll interval for timer irq | ||
558 | * | ||
559 | * This interval determines how frequent an interrupt is generated. | ||
560 | * The is value is determined by [(time_in_micro_secs * 100) / (2^10)] | ||
561 | * Min = 0, and Max = 65535 | ||
562 | */ | ||
563 | static int poll_interval = -1; | ||
564 | |||
541 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) | 565 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) |
542 | { | 566 | { |
543 | return netdev_priv(dev); | 567 | return netdev_priv(dev); |
@@ -1328,67 +1352,71 @@ static void nv_rx_process(struct net_device *dev) | |||
1328 | if (!(Flags & NV_RX_DESCRIPTORVALID)) | 1352 | if (!(Flags & NV_RX_DESCRIPTORVALID)) |
1329 | goto next_pkt; | 1353 | goto next_pkt; |
1330 | 1354 | ||
1331 | if (Flags & NV_RX_MISSEDFRAME) { | 1355 | if (Flags & NV_RX_ERROR) { |
1332 | np->stats.rx_missed_errors++; | 1356 | if (Flags & NV_RX_MISSEDFRAME) { |
1333 | np->stats.rx_errors++; | 1357 | np->stats.rx_missed_errors++; |
1334 | goto next_pkt; | ||
1335 | } | ||
1336 | if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) { | ||
1337 | np->stats.rx_errors++; | ||
1338 | goto next_pkt; | ||
1339 | } | ||
1340 | if (Flags & NV_RX_CRCERR) { | ||
1341 | np->stats.rx_crc_errors++; | ||
1342 | np->stats.rx_errors++; | ||
1343 | goto next_pkt; | ||
1344 | } | ||
1345 | if (Flags & NV_RX_OVERFLOW) { | ||
1346 | np->stats.rx_over_errors++; | ||
1347 | np->stats.rx_errors++; | ||
1348 | goto next_pkt; | ||
1349 | } | ||
1350 | if (Flags & NV_RX_ERROR4) { | ||
1351 | len = nv_getlen(dev, np->rx_skbuff[i]->data, len); | ||
1352 | if (len < 0) { | ||
1353 | np->stats.rx_errors++; | 1358 | np->stats.rx_errors++; |
1354 | goto next_pkt; | 1359 | goto next_pkt; |
1355 | } | 1360 | } |
1356 | } | 1361 | if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) { |
1357 | /* framing errors are soft errors. */ | 1362 | np->stats.rx_errors++; |
1358 | if (Flags & NV_RX_FRAMINGERR) { | 1363 | goto next_pkt; |
1359 | if (Flags & NV_RX_SUBSTRACT1) { | 1364 | } |
1360 | len--; | 1365 | if (Flags & NV_RX_CRCERR) { |
1366 | np->stats.rx_crc_errors++; | ||
1367 | np->stats.rx_errors++; | ||
1368 | goto next_pkt; | ||
1369 | } | ||
1370 | if (Flags & NV_RX_OVERFLOW) { | ||
1371 | np->stats.rx_over_errors++; | ||
1372 | np->stats.rx_errors++; | ||
1373 | goto next_pkt; | ||
1374 | } | ||
1375 | if (Flags & NV_RX_ERROR4) { | ||
1376 | len = nv_getlen(dev, np->rx_skbuff[i]->data, len); | ||
1377 | if (len < 0) { | ||
1378 | np->stats.rx_errors++; | ||
1379 | goto next_pkt; | ||
1380 | } | ||
1381 | } | ||
1382 | /* framing errors are soft errors. */ | ||
1383 | if (Flags & NV_RX_FRAMINGERR) { | ||
1384 | if (Flags & NV_RX_SUBSTRACT1) { | ||
1385 | len--; | ||
1386 | } | ||
1361 | } | 1387 | } |
1362 | } | 1388 | } |
1363 | } else { | 1389 | } else { |
1364 | if (!(Flags & NV_RX2_DESCRIPTORVALID)) | 1390 | if (!(Flags & NV_RX2_DESCRIPTORVALID)) |
1365 | goto next_pkt; | 1391 | goto next_pkt; |
1366 | 1392 | ||
1367 | if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { | 1393 | if (Flags & NV_RX2_ERROR) { |
1368 | np->stats.rx_errors++; | 1394 | if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) { |
1369 | goto next_pkt; | ||
1370 | } | ||
1371 | if (Flags & NV_RX2_CRCERR) { | ||
1372 | np->stats.rx_crc_errors++; | ||
1373 | np->stats.rx_errors++; | ||
1374 | goto next_pkt; | ||
1375 | } | ||
1376 | if (Flags & NV_RX2_OVERFLOW) { | ||
1377 | np->stats.rx_over_errors++; | ||
1378 | np->stats.rx_errors++; | ||
1379 | goto next_pkt; | ||
1380 | } | ||
1381 | if (Flags & NV_RX2_ERROR4) { | ||
1382 | len = nv_getlen(dev, np->rx_skbuff[i]->data, len); | ||
1383 | if (len < 0) { | ||
1384 | np->stats.rx_errors++; | 1395 | np->stats.rx_errors++; |
1385 | goto next_pkt; | 1396 | goto next_pkt; |
1386 | } | 1397 | } |
1387 | } | 1398 | if (Flags & NV_RX2_CRCERR) { |
1388 | /* framing errors are soft errors */ | 1399 | np->stats.rx_crc_errors++; |
1389 | if (Flags & NV_RX2_FRAMINGERR) { | 1400 | np->stats.rx_errors++; |
1390 | if (Flags & NV_RX2_SUBSTRACT1) { | 1401 | goto next_pkt; |
1391 | len--; | 1402 | } |
1403 | if (Flags & NV_RX2_OVERFLOW) { | ||
1404 | np->stats.rx_over_errors++; | ||
1405 | np->stats.rx_errors++; | ||
1406 | goto next_pkt; | ||
1407 | } | ||
1408 | if (Flags & NV_RX2_ERROR4) { | ||
1409 | len = nv_getlen(dev, np->rx_skbuff[i]->data, len); | ||
1410 | if (len < 0) { | ||
1411 | np->stats.rx_errors++; | ||
1412 | goto next_pkt; | ||
1413 | } | ||
1414 | } | ||
1415 | /* framing errors are soft errors */ | ||
1416 | if (Flags & NV_RX2_FRAMINGERR) { | ||
1417 | if (Flags & NV_RX2_SUBSTRACT1) { | ||
1418 | len--; | ||
1419 | } | ||
1392 | } | 1420 | } |
1393 | } | 1421 | } |
1394 | Flags &= NV_RX2_CHECKSUMMASK; | 1422 | Flags &= NV_RX2_CHECKSUMMASK; |
@@ -1612,6 +1640,17 @@ static void nv_set_multicast(struct net_device *dev) | |||
1612 | spin_unlock_irq(&np->lock); | 1640 | spin_unlock_irq(&np->lock); |
1613 | } | 1641 | } |
1614 | 1642 | ||
1643 | /** | ||
1644 | * nv_update_linkspeed: Setup the MAC according to the link partner | ||
1645 | * @dev: Network device to be configured | ||
1646 | * | ||
1647 | * The function queries the PHY and checks if there is a link partner. | ||
1648 | * If yes, then it sets up the MAC accordingly. Otherwise, the MAC is | ||
1649 | * set to 10 MBit HD. | ||
1650 | * | ||
1651 | * The function returns 0 if there is no link partner and 1 if there is | ||
1652 | * a good link partner. | ||
1653 | */ | ||
1615 | static int nv_update_linkspeed(struct net_device *dev) | 1654 | static int nv_update_linkspeed(struct net_device *dev) |
1616 | { | 1655 | { |
1617 | struct fe_priv *np = netdev_priv(dev); | 1656 | struct fe_priv *np = netdev_priv(dev); |
@@ -1751,13 +1790,11 @@ set_speed: | |||
1751 | static void nv_linkchange(struct net_device *dev) | 1790 | static void nv_linkchange(struct net_device *dev) |
1752 | { | 1791 | { |
1753 | if (nv_update_linkspeed(dev)) { | 1792 | if (nv_update_linkspeed(dev)) { |
1754 | if (netif_carrier_ok(dev)) { | 1793 | if (!netif_carrier_ok(dev)) { |
1755 | nv_stop_rx(dev); | ||
1756 | } else { | ||
1757 | netif_carrier_on(dev); | 1794 | netif_carrier_on(dev); |
1758 | printk(KERN_INFO "%s: link up.\n", dev->name); | 1795 | printk(KERN_INFO "%s: link up.\n", dev->name); |
1796 | nv_start_rx(dev); | ||
1759 | } | 1797 | } |
1760 | nv_start_rx(dev); | ||
1761 | } else { | 1798 | } else { |
1762 | if (netif_carrier_ok(dev)) { | 1799 | if (netif_carrier_ok(dev)) { |
1763 | netif_carrier_off(dev); | 1800 | netif_carrier_off(dev); |
@@ -1799,22 +1836,18 @@ static irqreturn_t nv_nic_irq(int foo, void *data, struct pt_regs *regs) | |||
1799 | if (!(events & np->irqmask)) | 1836 | if (!(events & np->irqmask)) |
1800 | break; | 1837 | break; |
1801 | 1838 | ||
1802 | if (events & (NVREG_IRQ_TX1|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_ERROR|NVREG_IRQ_TX_ERR)) { | 1839 | spin_lock(&np->lock); |
1840 | nv_tx_done(dev); | ||
1841 | spin_unlock(&np->lock); | ||
1842 | |||
1843 | nv_rx_process(dev); | ||
1844 | if (nv_alloc_rx(dev)) { | ||
1803 | spin_lock(&np->lock); | 1845 | spin_lock(&np->lock); |
1804 | nv_tx_done(dev); | 1846 | if (!np->in_shutdown) |
1847 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | ||
1805 | spin_unlock(&np->lock); | 1848 | spin_unlock(&np->lock); |
1806 | } | 1849 | } |
1807 | 1850 | ||
1808 | if (events & (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF)) { | ||
1809 | nv_rx_process(dev); | ||
1810 | if (nv_alloc_rx(dev)) { | ||
1811 | spin_lock(&np->lock); | ||
1812 | if (!np->in_shutdown) | ||
1813 | mod_timer(&np->oom_kick, jiffies + OOM_REFILL); | ||
1814 | spin_unlock(&np->lock); | ||
1815 | } | ||
1816 | } | ||
1817 | |||
1818 | if (events & NVREG_IRQ_LINK) { | 1851 | if (events & NVREG_IRQ_LINK) { |
1819 | spin_lock(&np->lock); | 1852 | spin_lock(&np->lock); |
1820 | nv_link_irq(dev); | 1853 | nv_link_irq(dev); |
@@ -2216,7 +2249,14 @@ static int nv_open(struct net_device *dev) | |||
2216 | writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed); | 2249 | writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed); |
2217 | writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1); | 2250 | writel(NVREG_UNKSETUP1_VAL, base + NvRegUnknownSetupReg1); |
2218 | writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2); | 2251 | writel(NVREG_UNKSETUP2_VAL, base + NvRegUnknownSetupReg2); |
2219 | writel(NVREG_POLL_DEFAULT, base + NvRegPollingInterval); | 2252 | if (poll_interval == -1) { |
2253 | if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) | ||
2254 | writel(NVREG_POLL_DEFAULT_THROUGHPUT, base + NvRegPollingInterval); | ||
2255 | else | ||
2256 | writel(NVREG_POLL_DEFAULT_CPU, base + NvRegPollingInterval); | ||
2257 | } | ||
2258 | else | ||
2259 | writel(poll_interval & 0xFFFF, base + NvRegPollingInterval); | ||
2220 | writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); | 2260 | writel(NVREG_UNKSETUP6_VAL, base + NvRegUnknownSetupReg6); |
2221 | writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, | 2261 | writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, |
2222 | base + NvRegAdapterControl); | 2262 | base + NvRegAdapterControl); |
@@ -2501,7 +2541,11 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2501 | } else { | 2541 | } else { |
2502 | np->tx_flags = NV_TX2_VALID; | 2542 | np->tx_flags = NV_TX2_VALID; |
2503 | } | 2543 | } |
2504 | np->irqmask = NVREG_IRQMASK_WANTED; | 2544 | if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) |
2545 | np->irqmask = NVREG_IRQMASK_THROUGHPUT; | ||
2546 | else | ||
2547 | np->irqmask = NVREG_IRQMASK_CPU; | ||
2548 | |||
2505 | if (id->driver_data & DEV_NEED_TIMERIRQ) | 2549 | if (id->driver_data & DEV_NEED_TIMERIRQ) |
2506 | np->irqmask |= NVREG_IRQ_TIMER; | 2550 | np->irqmask |= NVREG_IRQ_TIMER; |
2507 | if (id->driver_data & DEV_NEED_LINKTIMER) { | 2551 | if (id->driver_data & DEV_NEED_LINKTIMER) { |
@@ -2514,16 +2558,17 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2514 | } | 2558 | } |
2515 | 2559 | ||
2516 | /* find a suitable phy */ | 2560 | /* find a suitable phy */ |
2517 | for (i = 1; i < 32; i++) { | 2561 | for (i = 1; i <= 32; i++) { |
2518 | int id1, id2; | 2562 | int id1, id2; |
2563 | int phyaddr = i & 0x1F; | ||
2519 | 2564 | ||
2520 | spin_lock_irq(&np->lock); | 2565 | spin_lock_irq(&np->lock); |
2521 | id1 = mii_rw(dev, i, MII_PHYSID1, MII_READ); | 2566 | id1 = mii_rw(dev, phyaddr, MII_PHYSID1, MII_READ); |
2522 | spin_unlock_irq(&np->lock); | 2567 | spin_unlock_irq(&np->lock); |
2523 | if (id1 < 0 || id1 == 0xffff) | 2568 | if (id1 < 0 || id1 == 0xffff) |
2524 | continue; | 2569 | continue; |
2525 | spin_lock_irq(&np->lock); | 2570 | spin_lock_irq(&np->lock); |
2526 | id2 = mii_rw(dev, i, MII_PHYSID2, MII_READ); | 2571 | id2 = mii_rw(dev, phyaddr, MII_PHYSID2, MII_READ); |
2527 | spin_unlock_irq(&np->lock); | 2572 | spin_unlock_irq(&np->lock); |
2528 | if (id2 < 0 || id2 == 0xffff) | 2573 | if (id2 < 0 || id2 == 0xffff) |
2529 | continue; | 2574 | continue; |
@@ -2531,23 +2576,19 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
2531 | id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT; | 2576 | id1 = (id1 & PHYID1_OUI_MASK) << PHYID1_OUI_SHFT; |
2532 | id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT; | 2577 | id2 = (id2 & PHYID2_OUI_MASK) >> PHYID2_OUI_SHFT; |
2533 | dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n", | 2578 | dprintk(KERN_DEBUG "%s: open: Found PHY %04x:%04x at address %d.\n", |
2534 | pci_name(pci_dev), id1, id2, i); | 2579 | pci_name(pci_dev), id1, id2, phyaddr); |
2535 | np->phyaddr = i; | 2580 | np->phyaddr = phyaddr; |
2536 | np->phy_oui = id1 | id2; | 2581 | np->phy_oui = id1 | id2; |
2537 | break; | 2582 | break; |
2538 | } | 2583 | } |
2539 | if (i == 32) { | 2584 | if (i == 33) { |
2540 | /* PHY in isolate mode? No phy attached and user wants to | ||
2541 | * test loopback? Very odd, but can be correct. | ||
2542 | */ | ||
2543 | printk(KERN_INFO "%s: open: Could not find a valid PHY.\n", | 2585 | printk(KERN_INFO "%s: open: Could not find a valid PHY.\n", |
2544 | pci_name(pci_dev)); | 2586 | pci_name(pci_dev)); |
2545 | } | 2587 | goto out_freering; |
2546 | |||
2547 | if (i != 32) { | ||
2548 | /* reset it */ | ||
2549 | phy_init(dev); | ||
2550 | } | 2588 | } |
2589 | |||
2590 | /* reset it */ | ||
2591 | phy_init(dev); | ||
2551 | 2592 | ||
2552 | /* set default link speed settings */ | 2593 | /* set default link speed settings */ |
2553 | np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; | 2594 | np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; |
@@ -2689,6 +2730,10 @@ static void __exit exit_nic(void) | |||
2689 | 2730 | ||
2690 | module_param(max_interrupt_work, int, 0); | 2731 | module_param(max_interrupt_work, int, 0); |
2691 | MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt"); | 2732 | MODULE_PARM_DESC(max_interrupt_work, "forcedeth maximum events handled per interrupt"); |
2733 | module_param(optimization_mode, int, 0); | ||
2734 | MODULE_PARM_DESC(optimization_mode, "In throughput mode (0), every tx & rx packet will generate an interrupt. In CPU mode (1), interrupts are controlled by a timer."); | ||
2735 | module_param(poll_interval, int, 0); | ||
2736 | MODULE_PARM_DESC(poll_interval, "Interval determines how frequent timer interrupt is generated by [(time_in_micro_secs * 100) / (2^10)]. Min is 0 and Max is 65535."); | ||
2692 | 2737 | ||
2693 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); | 2738 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); |
2694 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); | 2739 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); |