summaryrefslogtreecommitdiffstats
path: root/drivers/net/3c59x.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/net/3c59x.c
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'drivers/net/3c59x.c')
-rw-r--r--drivers/net/3c59x.c244
1 files changed, 142 insertions, 102 deletions
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index d90732d8a..776345f21 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -9,7 +9,7 @@
Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597
and the EtherLink XL 3c900 and 3c905 cards.
- The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
+ The author may be reached as becker@scyld.com, or C/O
Center of Excellence in Space Data and Information Sciences
Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
@@ -53,7 +53,7 @@
- Increased the loop counter in wait_for_completion from 2,000 to 4,000.
LK1.1.5 28 April 2000, andrewm
- - Added powerpc defines
+ - Added powerpc defines (John Daniel <jdaniel@etresoft.com> said these work...)
- Some extra diagnostics
- In vortex_error(), reset the Tx on maxCollisions. Otherwise most
chips usually get a Tx timeout.
@@ -63,6 +63,20 @@
- In vortex_up(), don't make Wn3_config initialisation dependent upon has_nway
(this came across from 3c575_cb).
+ LK1.1.6 06 Jun 2000, andrewm
+ - Backed out the PPC defines.
+ - Use del_timer_sync(), mod_timer().
+ - Fix wrapped ulong comparison in boomerang_rx()
+ - Add IS_TORNADO, use it to suppress 3c905C checksum error msg
+ (Donald Becker, I Lee Hetherington <ilh@sls.lcs.mit.edu>)
+ - Replace union wn3_config with BFINS/BFEXT manipulation for
+ sparc64 (Pete Zaitcev, Peter Jones)
+ - In vortex_error, do_tx_reset and vortex_tx_timeout(Vortex):
+ do a netif_wake_queue() to better recover from errors. (Anders Pedersen,
+ Donald Becker)
+ - Print a warning on out-of-memory (rate limited to 1 per 10 secs)
+ - Added two more Cardbus 575 NICs: 5b57 and 6564 (Paul Wagland)
+
- See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details.
*/
@@ -75,6 +89,12 @@
* elimination of all the tests and reduced cache footprint.
*/
+/* A few values that may be tweaked. */
+/* Keep the ring sizes a power of two for efficiency. */
+#define TX_RING_SIZE 16
+#define RX_RING_SIZE 32
+#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
+
/* "Knobs" that adjust features and parameters. */
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1512 effectively disables this feature. */
@@ -85,6 +105,8 @@ static const int mtu = 1500;
static int max_interrupt_work = 32;
/* Give the NIC an extra reset at the end of vortex_up() */
static int extra_reset = 0;
+/* Tx timeout interval (millisecs) */
+static int watchdog = 400;
/* Allow aggregation of Tx interrupts. Saves CPU load at the cost
* of possible Tx stalls if the system is blocking interrupts
@@ -92,6 +114,7 @@ static int extra_reset = 0;
* AKPM 26 April 2000: enabling this still gets vestigial Tx timeouts
* in a heavily loaded (collision-prone) 10BaseT LAN. Should be OK with
* switched Ethernet.
+ * AKPM 24May00: vestigial timeouts have been removed by later fixes.
*/
#define tx_interrupt_mitigation 1
@@ -107,15 +130,6 @@ static int vortex_debug = 1;
debugging. */
static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
-/* A few values that may be tweaked. */
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT ((400*HZ)/1000)
-
-/* Keep the ring sizes a power of two for efficiency. */
-#define TX_RING_SIZE 16
-#define RX_RING_SIZE 32
-#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
-
#ifndef __OPTIMIZE__
#error You must compile this file with the correct options!
#error See the last lines of the source file.
@@ -141,12 +155,6 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#include <asm/bitops.h>
#include <asm/io.h>
-/* John Daniel <jdaniel@etresoft.com> said these work... */
-#ifdef __powerpc__
-#define outsl outsl_ns
-#define insl insl_ns
-#endif
-
/* Kernel compatibility defines, some common to David Hinds' PCMCIA package.
This is only in the support-all-kernels source code. */
@@ -155,9 +163,9 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0, rx_csumhits;
#include <linux/delay.h>
static char version[] __devinitdata =
-"3c59x.c:v0.99L+LK1.1.5 30 Apr 2000 Donald Becker and others http://cesdis.gsfc.nasa.gov/linux/drivers/vortex.html " "$Revision: 1.78 $\n";
+"3c59x.c:v0.99L+LK1.1.6 28 May 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.97 $\n";
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver");
MODULE_PARM(debug, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
@@ -168,6 +176,7 @@ MODULE_PARM(extra_reset, "i");
MODULE_PARM(compaq_ioaddr, "i");
MODULE_PARM(compaq_irq, "i");
MODULE_PARM(compaq_device_id, "i");
+MODULE_PARM(watchdog, "i");
/* Operational parameter that usually are not changed. */
@@ -271,9 +280,9 @@ enum pci_flags_bit {
PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
};
-enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4,
- EEPROM_230=8, /* AKPM: Uses 0x230 as the base bitmpas for EEPROM reads */
- HAS_PWR_CTRL=0x10, HAS_MII=0x20, HAS_NWAY=0x40, HAS_CB_FNS=0x80, };
+enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8,
+ EEPROM_230=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */
+ HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, };
enum vortex_chips {
@@ -284,31 +293,33 @@ enum vortex_chips {
CH_3C595_2,
CH_3C595_3,
- CH_VORTEX,
CH_3C900_1,
CH_3C900_2,
CH_3C900_3,
-
CH_3C900_4,
+
CH_3C900_5,
CH_3C900B_FL,
CH_3C905_1,
CH_3C905_2,
-
CH_3C905B_1,
+
CH_3C905B_2,
CH_3C905B_FX,
CH_3C905C,
CH_3C980,
+ CH_3C9805,
CH_3CSOHO100_TX,
CH_3C555,
+ CH_3C575,
CH_3C575_1,
CH_3CCFE575,
- CH_3CCFE575CT,
+ CH_3CCFE575CT,
CH_3CCFE656,
CH_3CCFEM656,
+ CH_3CCFEM656_1,
CH_3C450,
};
@@ -323,6 +334,7 @@ static struct vortex_chip_info {
int drv_flags;
int io_size;
} vortex_info_tbl[] __devinitdata = {
+#define EISA_TBL_OFFSET 0 /* Offset of this entry for vortex_eisa_init */
{"3c590 Vortex 10Mbps",
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
{"3c592 EISA 10mbps Demon/Vortex", /* AKPM: from Don's 3c59x_cb.c 0.49H */
@@ -336,18 +348,15 @@ static struct vortex_chip_info {
{"3c595 Vortex 100base-MII",
PCI_USES_IO|PCI_USES_MASTER, IS_VORTEX, 32, },
-#define EISA_TBL_OFFSET 6 /* Offset of this entry for vortex_eisa_init */
- {"3Com Vortex",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
{"3c900 Boomerang 10baseT",
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
{"3c900 Boomerang 10Mbps Combo",
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, },
{"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
-
{"3c900 Cyclone 10Mbps Combo",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+
{"3c900 Cyclone 10Mbps TPC", /* AKPM: from Don's 0.99M */
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
{"3c900B-FL Cyclone 10base-FL",
@@ -356,35 +365,42 @@ static struct vortex_chip_info {
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
{"3c905 Boomerang 100baseT4",
PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII, 64, },
-
{"3c905B Cyclone 100baseTx",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
+
{"3c905B Cyclone 10/100/BNC",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
{"3c905B-FX Cyclone 100baseFx",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
{"3c905C Tornado",
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, },
{"3c980 Cyclone",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c980 10/100 Base-TX NIC(Python-T)",
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
{"3cSOHO100-TX Hurricane",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
{"3c555 Laptop Hurricane",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, },
+ {"3c575 [Megahertz] 10/100 LAN CardBus",
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, },
{"3c575 Boomerang CardBus",
- PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 64, },
+ PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_230, 128, },
{"3CCFE575 Cyclone CardBus",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
+
{"3CCFE575CT Cyclone CardBus",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
-
{"3CCFE656 Cyclone CardBus",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
{"3CCFEM656 Cyclone CardBus",
PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
- {"3c450 Cyclone/unknown", /* AKPM: from Don's 0.99N */
- PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, },
+ {"3CCFEM656 Cyclone CardBus(0x6564)", /* From pcmcia-cs-3.1.5 */
+ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_230, 128, },
+ {"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */
+ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, },
+
{0,}, /* 0 terminated list. */
};
@@ -397,32 +413,35 @@ static struct pci_device_id vortex_pci_tbl[] __devinitdata = {
{ 0x10B7, 0x5951, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_2 },
{ 0x10B7, 0x5952, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C595_3 },
- { 0x10B7, 0x5900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VORTEX },
{ 0x10B7, 0x9000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_1 },
{ 0x10B7, 0x9001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_2 },
{ 0x10B7, 0x9004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_3 },
-
{ 0x10B7, 0x9005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_4 },
+
{ 0x10B7, 0x9006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900_5 },
{ 0x10B7, 0x900A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C900B_FL },
{ 0x10B7, 0x9050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_1 },
{ 0x10B7, 0x9051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905_2 },
-
{ 0x10B7, 0x9055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_1 },
+
{ 0x10B7, 0x9058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_2 },
{ 0x10B7, 0x905A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905B_FX },
{ 0x10B7, 0x9200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C905C },
{ 0x10B7, 0x9800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C980 },
+ { 0x10B7, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C9805 },
{ 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX },
{ 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 },
+ { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 },
{ 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 },
{ 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 },
- { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
+ { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT },
{ 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
{ 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
+ { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 },
{ 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
+
{0,} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
@@ -501,15 +520,21 @@ enum Window2 { /* Window 2. */
enum Window3 { /* Window 3: MAC/config bits. */
Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8,
};
-union wn3_config {
- int i;
- struct w3_config_fields {
- unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
- int pad8:8;
- unsigned int ram_split:2, pad18:2, xcvr:4, autoselect:1;
- int pad24:7;
- } u;
-};
+
+#define BFEXT(value, offset, bitcount) \
+ ((((unsigned long)(value)) >> (offset)) & ((1 << (bitcount)) - 1))
+
+#define BFINS(lhs, rhs, offset, bitcount) \
+ (((lhs) & ~((((1 << (bitcount)) - 1)) << (offset))) | \
+ (((rhs) & ((1 << (bitcount)) - 1)) << (offset)))
+
+#define RAM_SIZE(v) BFEXT(v, 0, 3)
+#define RAM_WIDTH(v) BFEXT(v, 3, 1)
+#define RAM_SPEED(v) BFEXT(v, 4, 2)
+#define ROM_SIZE(v) BFEXT(v, 6, 2)
+#define RAM_SPLIT(v) BFEXT(v, 16, 2)
+#define XCVR(v) BFEXT(v, 20, 4)
+#define AUTOSELECT(v) BFEXT(v, 24, 1)
enum Window4 { /* Window 4: Xcvr/media bits. */
Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10,
@@ -532,7 +557,8 @@ enum MasterCtrl {
/* The Rx and Tx descriptor lists.
Caution Alpha hackers: these types are 32 bits! Note also the 8 byte
alignment contraint on tx_ring[] and rx_ring[]. */
-#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */
+#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */
+#define DN_COMPLETE 0x00010000 /* This packet has been downloaded */
struct boom_rx_desc {
u32 next; /* Last entry points to 0. */
s32 status;
@@ -785,6 +811,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
struct net_device *dev;
static int printed_version = 0;
int retval;
+ struct vortex_chip_info * const vci = &vortex_info_tbl[chip_idx];
if (!printed_version) {
printk (KERN_INFO "%s", version);
@@ -801,7 +828,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ",
dev->name,
pdev ? "PCI" : "EISA",
- vortex_info_tbl[chip_idx].name,
+ vci->name,
ioaddr);
/* private struct aligned and zeroed by init_etherdev */
@@ -809,8 +836,8 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
dev->base_addr = ioaddr;
dev->irq = irq;
dev->mtu = mtu;
- vp->has_nway = (vortex_info_tbl[chip_idx].drv_flags & HAS_NWAY) ? 1 : 0;
- vp->io_size = vortex_info_tbl[chip_idx].io_size;
+ vp->has_nway = (vci->drv_flags & HAS_NWAY) ? 1 : 0;
+ vp->io_size = vci->io_size;
/* module list only for EISA devices */
if (pdev == NULL) {
@@ -821,10 +848,9 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
/* PCI-only startup logic */
if (pdev) {
/* EISA resources already marked, so only PCI needs to do this here */
- if (!request_region (ioaddr, vortex_info_tbl[chip_idx].io_size,
- dev->name)) {
+ if (!request_region (ioaddr, vci->io_size, dev->name)) {
printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n",
- dev->name, vortex_info_tbl[chip_idx].io_size, ioaddr);
+ dev->name, vci->io_size, ioaddr);
retval = -EBUSY;
goto free_dev;
}
@@ -836,7 +862,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
}
/* enable bus-mastering if necessary */
- if (vortex_info_tbl[chip_idx].flags & PCI_USES_MASTER)
+ if (vci->flags & PCI_USES_MASTER)
pci_set_master (pdev);
}
@@ -891,7 +917,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
{
- int base = (vortex_info_tbl[chip_idx].drv_flags & EEPROM_230) ? 0x230 : EEPROM_Read;
+ int base = (vci->drv_flags & EEPROM_230) ? 0x230 : EEPROM_Read;
for (i = 0; i < 0x40; i++) {
int timer;
outw(base + i, ioaddr + Wn0EepromCmd);
@@ -912,7 +938,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
checksum ^= eeprom[i++];
checksum = (checksum ^ (checksum >> 8)) & 0xff;
}
- if (checksum != 0x00)
+ if ((checksum != 0x00) && !(vci->drv_flags & IS_TORNADO))
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
for (i = 0; i < 3; i++)
((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
@@ -932,7 +958,7 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
dev->irq);
#endif
- if (pdev && vortex_info_tbl[chip_idx].drv_flags & HAS_CB_FNS) {
+ if (pdev && vci->drv_flags & HAS_CB_FNS) {
u32 fn_st_addr; /* Cardbus function status space */
fn_st_addr = pci_resource_start (pdev, 2);
if (fn_st_addr)
@@ -960,24 +986,24 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
{
static const char * ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
- union wn3_config config;
+ unsigned int config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */
vp->available_media = 0x40;
- config.i = inl(ioaddr + Wn3_Config);
+ config = inl(ioaddr + Wn3_Config);
if (vortex_debug > 1)
printk(KERN_DEBUG " Internal config register is %4.4x, "
- "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options));
+ "transceivers %#x.\n", config, inw(ioaddr + Wn3_Options));
printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
- 8 << config.u.ram_size,
- config.u.ram_width ? "word" : "byte",
- ram_split[config.u.ram_split],
- config.u.autoselect ? "autoselect/" : "",
- config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" :
- media_tbl[config.u.xcvr].name);
- vp->default_media = config.u.xcvr;
- vp->autoselect = config.u.autoselect;
+ 8 << RAM_SIZE(config),
+ RAM_WIDTH(config) ? "word" : "byte",
+ ram_split[RAM_SPLIT(config)],
+ AUTOSELECT(config) ? "autoselect/" : "",
+ XCVR(config) > XCVR_ExtMII ? "<invalid transceiver>" :
+ media_tbl[XCVR(config)].name);
+ vp->default_media = XCVR(config);
+ vp->autoselect = AUTOSELECT(config);
}
if (vp->media_override != 7) {
@@ -1037,12 +1063,12 @@ static int __devinit vortex_probe1(struct pci_dev *pdev,
dev->do_ioctl = &vortex_ioctl;
dev->set_multicast_list = &set_rx_mode;
dev->tx_timeout = &vortex_tx_timeout;
- dev->watchdog_timeo = TX_TIMEOUT;
+ dev->watchdog_timeo = (watchdog * HZ) / 1000;
return 0;
free_region:
- release_region (ioaddr, vortex_info_tbl[chip_idx].io_size);
+ release_region (ioaddr, vci->io_size);
free_dev:
unregister_netdev(dev);
kfree (dev);
@@ -1070,7 +1096,7 @@ vortex_up(struct net_device *dev)
{
long ioaddr = dev->base_addr;
struct vortex_private *vp = (struct vortex_private *)dev->priv;
- union wn3_config config;
+ unsigned int config;
int i, device_id;
if (vp->pdev)
@@ -1080,7 +1106,7 @@ vortex_up(struct net_device *dev)
/* Before initializing select the active media port. */
EL3WINDOW(3);
- config.i = inl(ioaddr + Wn3_Config);
+ config = inl(ioaddr + Wn3_Config);
if (vp->media_override != 7) {
if (vortex_debug > 1)
@@ -1118,13 +1144,13 @@ vortex_up(struct net_device *dev)
dev->name, media_tbl[dev->if_port].name);
vp->full_duplex = vp->force_fd;
- config.u.xcvr = dev->if_port;
+ config = BFINS(config, dev->if_port, 20, 4);
//AKPM if (!vp->has_nway)
{
if (vortex_debug > 6)
printk(KERN_DEBUG "vortex_up(): writing 0x%x to InternalConfig\n",
- config.i);
- outl(config.i, ioaddr + Wn3_Config);
+ config);
+ outl(config, ioaddr + Wn3_Config);
}
if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) {
@@ -1151,7 +1177,7 @@ vortex_up(struct net_device *dev)
if (vortex_debug > 1) {
printk(KERN_DEBUG "%s: vortex_up() InternalConfig %8.8x.\n",
- dev->name, config.i);
+ dev->name, config);
}
wait_for_completion(dev, TxReset);
@@ -1233,8 +1259,6 @@ vortex_up(struct net_device *dev)
set_rx_mode(dev);
outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
- netif_start_queue (dev);
-
outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
/* Allow status bits to be seen. */
@@ -1264,6 +1288,7 @@ vortex_up(struct net_device *dev)
}
outw(TxEnable, ioaddr + EL3_CMD);
}
+ netif_start_queue (dev);
}
static int
@@ -1321,9 +1346,11 @@ static void vortex_timer(unsigned long data)
int ok = 0;
int media_status, mii_status, old_window;
- if (vortex_debug > 1)
+ if (vortex_debug > 1) {
printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n",
dev->name, media_tbl[dev->if_port].name);
+ printk(KERN_DEBUG "dev->watchdog_timeo=%d\n", dev->watchdog_timeo);
+ }
disable_irq(dev->irq);
old_window = inw(ioaddr + EL3_CMD) >> 13;
@@ -1383,7 +1410,7 @@ static void vortex_timer(unsigned long data)
ok = 1;
}
if ( ! ok) {
- union wn3_config config;
+ unsigned int config;
do {
dev->if_port = media_tbl[dev->if_port].next;
@@ -1405,14 +1432,14 @@ static void vortex_timer(unsigned long data)
media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
EL3WINDOW(3);
- config.i = inl(ioaddr + Wn3_Config);
- config.u.xcvr = dev->if_port;
- outl(config.i, ioaddr + Wn3_Config);
+ config = inl(ioaddr + Wn3_Config);
+ config = BFINS(config, dev->if_port, 20, 4);
+ outl(config, ioaddr + Wn3_Config);
outw(dev->if_port == XCVR_10base2 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
if (vortex_debug > 1)
- printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config.i);
+ printk(KERN_DEBUG "wrote 0x%08x to Wn3_Config\n", config);
/* AKPM: FIXME: Should reset Rx & Tx here. P60 of 3c90xc.pdf */
}
EL3WINDOW(old_window);
@@ -1422,10 +1449,10 @@ static void vortex_timer(unsigned long data)
printk(KERN_DEBUG "%s: Media selection timer finished, %s.\n",
dev->name, media_tbl[dev->if_port].name);
- vp->timer.expires = RUN_AT(next_tick);
- add_timer(&vp->timer);
+ mod_timer(&vp->timer, RUN_AT(next_tick));
if (vp->deferred)
outw(FakeIntr, ioaddr + EL3_CMD);
+ timer_exit(&vp->timer);
return;
}
@@ -1437,6 +1464,7 @@ static void vortex_tx_timeout(struct net_device *dev)
printk(KERN_ERR "%s: transmit timed out, tx_status %2.2x status %4.4x.\n",
dev->name, inb(ioaddr + TxStatus),
inw(ioaddr + EL3_STATUS));
+
/* Slight code bloat to be user friendly. */
if ((inb(ioaddr + TxStatus) & 0x88) == 0x88)
printk(KERN_ERR "%s: Transmitter encountered 16 collisions --"
@@ -1460,7 +1488,7 @@ static void vortex_tx_timeout(struct net_device *dev)
}
}
- if (vortex_debug > 1)
+ if (vortex_debug > 0)
dump_tx_ring(dev);
wait_for_completion(dev, TxReset);
@@ -1481,8 +1509,10 @@ static void vortex_tx_timeout(struct net_device *dev)
netif_stop_queue (dev);
outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold);
outw(DownUnstall, ioaddr + EL3_CMD);
- } else
+ } else {
vp->stats.tx_dropped++;
+ netif_wake_queue(dev);
+ }
/* Issue Tx Enable */
outw(TxEnable, ioaddr + EL3_CMD);
@@ -1607,6 +1637,7 @@ vortex_error(struct net_device *dev, int status)
} else {
wait_for_completion(dev, TxReset);
outw(TxEnable, ioaddr + EL3_CMD);
+ netif_wake_queue(dev);
}
}
}
@@ -1875,9 +1906,15 @@ static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
outw(AckIntr | DownComplete, ioaddr + EL3_CMD);
while (vp->cur_tx - dirty_tx > 0) {
int entry = dirty_tx % TX_RING_SIZE;
+#if 1 /* AKPM: the latter is faster, but cyclone-only */
if (inl(ioaddr + DownListPtr) ==
vp->tx_ring_dma + entry * sizeof(struct boom_tx_desc))
break; /* It still hasn't been processed. */
+#else
+ if ((vp->tx_ring[entry].status & DN_COMPLETE) == 0)
+ break; /* It still hasn't been processed. */
+#endif
+
if (vp->tx_skbuff[entry]) {
struct sk_buff *skb = vp->tx_skbuff[entry];
@@ -1899,8 +1936,6 @@ static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
netif_wake_queue (dev);
}
}
- if (vp->tx_full)
- netif_stop_queue (dev);
/* Check for all uncommon interrupts at once. */
if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq))
@@ -1925,7 +1960,7 @@ static void boomerang_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (vp->cb_fn_base) /* The PCMCIA people are idiots. */
writel(0x8000, vp->cb_fn_base + 4);
- } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete));
+ } while ((status = inw(ioaddr + EL3_STATUS)) & IntLatch);
if (vortex_debug > 4)
printk(KERN_DEBUG "%s: exiting interrupt, status %4.4x.\n",
@@ -2041,8 +2076,7 @@ boomerang_rx(struct net_device *dev)
/* Check if the packet is long enough to just accept without
copying to a properly sized skbuff. */
- if (pkt_len < rx_copybreak
- && (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
+ if (pkt_len < rx_copybreak && (skb = dev_alloc_skb(pkt_len + 2)) != 0) {
skb->dev = dev;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
pci_dma_sync_single(vp->pdev, dma, PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
@@ -2076,13 +2110,19 @@ boomerang_rx(struct net_device *dev)
entry = (++vp->cur_rx) % RX_RING_SIZE;
}
/* Refill the Rx ring buffers. */
- for (; vp->dirty_rx < vp->cur_rx; vp->dirty_rx++) {
+ for (; vp->cur_rx - vp->dirty_rx > 0; vp->dirty_rx++) {
struct sk_buff *skb;
entry = vp->dirty_rx % RX_RING_SIZE;
if (vp->rx_skbuff[entry] == NULL) {
skb = dev_alloc_skb(PKT_BUF_SZ);
- if (skb == NULL)
+ if (skb == NULL) {
+ static unsigned long last_jif;
+ if ((jiffies - last_jif) > 10 * HZ) {
+ printk(KERN_WARNING "%s: memory shortage\n", dev->name);
+ last_jif = jiffies;
+ }
break; /* Bad news! */
+ }
skb->dev = dev; /* Mark as being used by this device. */
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
vp->rx_ring[entry].addr = cpu_to_le32(pci_map_single(vp->pdev, skb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
@@ -2102,7 +2142,7 @@ vortex_down(struct net_device *dev)
netif_stop_queue (dev);
- del_timer(&vp->timer);
+ del_timer_sync(&vp->timer);
/* Turn off statistics ASAP. We update vp->stats below. */
outw(StatsDisable, ioaddr + EL3_CMD);
@@ -2184,16 +2224,16 @@ dump_tx_ring(struct net_device *dev)
int stalled = inl(ioaddr + PktStatus) & 0x04; /* Possible racy. But it's only debug stuff */
wait_for_completion(dev, DownStall);
- printk(KERN_DEBUG " Flags; bus-master %d, full %d; dirty %d(%d) "
+ printk(KERN_ERR " Flags; bus-master %d, full %d; dirty %d(%d) "
"current %d(%d).\n",
vp->full_bus_master_tx, vp->tx_full,
vp->dirty_tx, vp->dirty_tx % TX_RING_SIZE,
vp->cur_tx, vp->cur_tx % TX_RING_SIZE);
- printk(KERN_DEBUG " Transmit list %8.8x vs. %p.\n",
+ printk(KERN_ERR " Transmit list %8.8x vs. %p.\n",
inl(ioaddr + DownListPtr),
&vp->tx_ring[vp->dirty_tx % TX_RING_SIZE]);
for (i = 0; i < TX_RING_SIZE; i++) {
- printk(KERN_DEBUG " %d: @%p length %8.8x status %8.8x\n", i,
+ printk(KERN_ERR " %d: @%p length %8.8x status %8.8x\n", i,
&vp->tx_ring[i],
le32_to_cpu(vp->tx_ring[i].length),
le32_to_cpu(vp->tx_ring[i].status));