From c703524d943597d67df430a8fe322215fd9e7866 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:31:13 -0500 Subject: [PATCH] Import 2.3.44pre8 --- drivers/net/3c507.c | 2 +- drivers/net/3c515.c | 1196 ++++++++++++++++++++++-------------------- drivers/net/cops.c | 166 +++--- drivers/net/de600.c | 38 +- drivers/net/fmv18x.c | 194 ++++--- drivers/net/ni5010.c | 98 ++-- drivers/net/ni52.c | 138 ++--- 7 files changed, 897 insertions(+), 935 deletions(-) diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 9e309be5ff1c..3a3f6b293758 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -453,6 +453,7 @@ static void el16_tx_timeout (struct net_device *dev) { struct net_local *lp = (struct net_local *) dev->priv; int ioaddr = dev->base_addr; + unsigned long shmem = dev->mem_start; if (net_debug > 1) printk ("%s: transmit timed out, %s? ", dev->name, @@ -481,7 +482,6 @@ static int el16_send_packet (struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local *) dev->priv; int ioaddr = dev->base_addr; - unsigned long shmem = dev->mem_start; unsigned long flags; short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c index 188d912b45db..06483f9aca51 100644 --- a/drivers/net/3c515.c +++ b/drivers/net/3c515.c @@ -10,17 +10,22 @@ The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 + + Cleaned up for 2.3.x/softnet by Jeff Garzik and Alan Cox. */ -static char *version = "3c515.c:v0.99 4/7/98 becker@cesdis.gsfc.nasa.gov\n"; +static char *version = "3c515.c:v0.99-sn 2000/02/12 becker@cesdis.gsfc.nasa.gov and others\n"; + #define CORKSCREW 1 /* "Knobs" that adjust features and parameters. */ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1512 effectively disables this feature. */ static const int rx_copybreak = 200; + /* Allow setting MTU to a larger size, bypassing the normal ethernet setup. */ static const int mtu = 1500; + /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 20; @@ -37,7 +42,7 @@ static int max_interrupt_work = 20; /* Keep the ring sizes a power of two for efficiency. */ #define TX_RING_SIZE 16 #define RX_RING_SIZE 16 -#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ +#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer. */ #include #include @@ -65,15 +70,10 @@ static int max_interrupt_work = 20; /* Kernel version compatibility functions. */ #define RUN_AT(x) (jiffies + (x)) -#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2) -#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev) #define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance) #define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs) -#if (LINUX_VERSION_CODE < 0x20123) -#define test_and_set_bit(val, addr) set_bit(val, addr) -#elif defined(MODULE) MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver"); MODULE_PARM(debug, "i"); @@ -81,7 +81,6 @@ MODULE_PARM(options, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(max_interrupt_work, "i"); -#endif /* "Knobs" for adjusting internal parameters. */ /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */ @@ -102,15 +101,10 @@ static int rx_nocopy = 0, rx_copy = 0, queued_packet = 0; */ #define CORKSCREW_TOTAL_SIZE 0x20 -#ifdef HAVE_DEVLIST -struct netdev_entry tc515_drv = -{"3c515", tc515_probe, CORKSCREW_TOTAL_SIZE, NULL}; -#endif - #ifdef DRIVER_DEBUG -int vortex_debug = DRIVER_DEBUG; +int corkscrew_debug = DRIVER_DEBUG; #else -int vortex_debug = 1; +int corkscrew_debug = 1; #endif #define CORKSCREW_ID 10 @@ -149,8 +143,8 @@ correctly-sized skbuff. IIIC. Synchronization The driver runs as two independent, single-threaded flows of control. One -is the send-packet routine, which enforces single-threaded use by the -dev->tbusy flag. The other thread is the interrupt handler, which is single +is the send-packet routine, which enforces single-threaded use by the netif +layer. The other thread is the interrupt handler, which is single threaded by the hardware and other software. IV. Notes @@ -184,87 +178,98 @@ of 1.5K, but the changes to support 4.5K are minimal. can handle FDDI length frames (~4500 octets) and now parameters count 32-bit 'Dwords' rather than octets. */ -enum vortex_cmd { - TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, - RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, - UpStall = 6<<11, UpUnstall = (6<<11)+1, - DownStall = (6<<11)+2, DownUnstall = (6<<11)+3, - RxDiscard = 8<<11, TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, - FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, - SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, - SetTxThreshold = 18<<11, SetTxStart = 19<<11, - StartDMAUp = 20<<11, StartDMADown = (20<<11)+1, StatsEnable = 21<<11, - StatsDisable = 22<<11, StopCoax = 23<<11,}; +enum corkscrew_cmd { + TotalReset = 0 << 11, SelectWindow = 1 << 11, StartCoax = 2 << 11, + RxDisable = 3 << 11, RxEnable = 4 << 11, RxReset = 5 << 11, + UpStall = 6 << 11, UpUnstall = (6 << 11) + 1, + DownStall = (6 << 11) + 2, DownUnstall = (6 << 11) + 3, + RxDiscard = 8 << 11, TxEnable = 9 << 11, TxDisable = + 10 << 11, TxReset = 11 << 11, + FakeIntr = 12 << 11, AckIntr = 13 << 11, SetIntrEnb = 14 << 11, + SetStatusEnb = 15 << 11, SetRxFilter = 16 << 11, SetRxThreshold = + 17 << 11, + SetTxThreshold = 18 << 11, SetTxStart = 19 << 11, + StartDMAUp = 20 << 11, StartDMADown = (20 << 11) + 1, StatsEnable = + 21 << 11, + StatsDisable = 22 << 11, StopCoax = 23 << 11, +}; /* The SetRxFilter command accepts the following classes: */ enum RxFilter { - RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 }; + RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 +}; /* Bits in the general status register. */ -enum vortex_status { +enum corkscrew_status { IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, IntReq = 0x0040, StatsFull = 0x0080, - DMADone = 1<<8, DownComplete = 1<<9, UpComplete = 1<<10, - DMAInProgress = 1<<11, /* DMA controller is still busy.*/ - CmdInProgress = 1<<12, /* EL3_CMD is still busy.*/ + DMADone = 1 << 8, DownComplete = 1 << 9, UpComplete = 1 << 10, + DMAInProgress = 1 << 11, /* DMA controller is still busy. */ + CmdInProgress = 1 << 12, /* EL3_CMD is still busy. */ }; /* Register window 1 offsets, the window used in normal operation. On the Corkscrew this window is always mapped at offsets 0x10-0x1f. */ enum Window1 { - TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, - RxStatus = 0x18, Timer=0x1A, TxStatus = 0x1B, - TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ + TX_FIFO = 0x10, RX_FIFO = 0x10, RxErrors = 0x14, + RxStatus = 0x18, Timer = 0x1A, TxStatus = 0x1B, + TxFree = 0x1C, /* Remaining free bytes in Tx buffer. */ }; enum Window0 { - Wn0IRQ = 0x08, + Wn0IRQ = 0x08, #if defined(CORKSCREW) - Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */ - Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */ + Wn0EepromCmd = 0x200A, /* Corkscrew EEPROM command register. */ + Wn0EepromData = 0x200C, /* Corkscrew EEPROM results register. */ #else - Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ - Wn0EepromData = 12, /* Window 0: EEPROM results register. */ + Wn0EepromCmd = 10, /* Window 0: EEPROM command register. */ + Wn0EepromData = 12, /* Window 0: EEPROM results register. */ #endif }; enum Win0_EEPROM_bits { EEPROM_Read = 0x80, EEPROM_WRITE = 0x40, EEPROM_ERASE = 0xC0, - EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ - EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ + EEPROM_EWENB = 0x30, /* Enable erasing/writing for 10 msec. */ + EEPROM_EWDIS = 0x00, /* Disable EWENB before 10 msec timeout. */ }; + /* EEPROM locations. */ enum eeprom_offset { - PhysAddr01=0, PhysAddr23=1, PhysAddr45=2, ModelID=3, - EtherLink3ID=7, }; + PhysAddr01 = 0, PhysAddr23 = 1, PhysAddr45 = 2, ModelID = 3, + EtherLink3ID = 7, +}; enum Window3 { /* Window 3: MAC/config bits. */ - Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, + 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; + 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:3, pad21:1, autoselect:1; + unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, + autoselect:1; int pad24:7; } u; }; enum Window4 { - Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */ + Wn4_NetDiag = 6, Wn4_Media = 10, /* Window 4: Xcvr/media bits. */ }; enum Win4_Media_bits { - Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */ + Media_SQE = 0x0008, /* Enable SQE error counting for AUI. */ Media_10TP = 0x00C0, /* Enable link beat and jabber for 10baseT. */ - Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */ + Media_Lnk = 0x0080, /* Enable just link beat for 100TX/100FX. */ Media_LnkBeat = 0x0800, }; -enum Window7 { /* Window 7: Bus Master control. */ +enum Window7 { /* Window 7: Bus Master control. */ Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12, }; + /* Boomerang-style bus master control registers. Note ISA aliases! */ enum MasterCtrl { - PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = 0x40c, + PktStatus = 0x400, DownListPtr = 0x404, FragAddr = 0x408, FragLen = + 0x40c, TxFreeThreshold = 0x40f, UpPktStatus = 0x410, UpListPtr = 0x418, }; @@ -277,9 +282,10 @@ struct boom_rx_desc { u32 addr; s32 length; }; + /* Values for the Rx status entry. */ enum rx_desc_status { - RxDComplete=0x00008000, RxDError=0x4000, + RxDComplete = 0x00008000, RxDError = 0x4000, /* See boomerang_rx() for actual error bits */ }; @@ -290,111 +296,112 @@ struct boom_tx_desc { s32 length; }; -struct vortex_private { - char devname[8]; /* "ethN" string, also for kernel debug. */ +struct corkscrew_private { + char devname[8]; /* "ethN" string, also for kernel debug. */ const char *product_name; struct net_device *next_module; /* The Rx and Tx rings are here to keep them quad-word-aligned. */ struct boom_rx_desc rx_ring[RX_RING_SIZE]; struct boom_tx_desc tx_ring[TX_RING_SIZE]; /* The addresses of transmit- and receive-in-place skbuffs. */ - struct sk_buff* rx_skbuff[RX_RING_SIZE]; - struct sk_buff* tx_skbuff[TX_RING_SIZE]; - unsigned int cur_rx, cur_tx; /* The next free ring entry */ - unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ + struct sk_buff *rx_skbuff[RX_RING_SIZE]; + struct sk_buff *tx_skbuff[TX_RING_SIZE]; + unsigned int cur_rx, cur_tx; /* The next free ring entry */ + unsigned int dirty_rx, dirty_tx;/* The ring entries to be free()ed. */ struct enet_statistics stats; - struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ + struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ struct timer_list timer; /* Media selection timer. */ - int capabilities; /* Adapter capabilities word. */ - int options; /* User-settable misc. driver options. */ + int capabilities ; /* Adapter capabilities word. */ + int options; /* User-settable misc. driver options. */ int last_rx_packets; /* For media autoselection. */ unsigned int available_media:8, /* From Wn3_Options */ - media_override:3, /* Passed-in media type. */ - default_media:3, /* Read from the EEPROM. */ - full_duplex:1, autoselect:1, - bus_master:1, /* Vortex can only do a fragment bus-m. */ - full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */ - tx_full:1; + media_override:3, /* Passed-in media type. */ + default_media:3, /* Read from the EEPROM. */ + full_duplex:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */ + full_bus_master_tx:1, full_bus_master_rx:1, /* Boomerang */ + tx_full:1; }; /* The action to take with a media selection timer tick. Note that we deviate from the 3Com order by checking 10base2 before AUI. */ enum xcvr_types { - XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, - XCVR_100baseFx, XCVR_MII=6, XCVR_Default=8, + XCVR_10baseT = + 0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, + XCVR_100baseFx, XCVR_MII = 6, XCVR_Default = 8, }; static struct media_table { - char *name; - unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ - mask:8, /* The transceiver-present bit in Wn3_Config.*/ - next:8; /* The media type to try next. */ - short wait; /* Time before we check media status. */ -} media_tbl[] = { - { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10}, - { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10}, - { "undefined", 0, 0x80, XCVR_10baseT, 10000}, - { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10}, - { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10}, - { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10}, - { "MII", 0, 0x40, XCVR_10baseT, 3*HZ }, - { "undefined", 0, 0x01, XCVR_10baseT, 10000}, - { "Default", 0, 0xFF, XCVR_10baseT, 10000}, + char *name; + unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ + mask:8, /* The transceiver-present bit in Wn3_Config. */ + next:8; /* The media type to try next. */ + short wait; /* Time before we check media status. */ +} media_tbl[] = { + { "10baseT", Media_10TP, 0x08, XCVR_10base2, (14 * HZ) / 10 }, + { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1 * HZ) / 10}, + { "undefined", 0, 0x80, XCVR_10baseT, 10000}, + { "10base2", 0, 0x10, XCVR_AUI, (1 * HZ) / 10}, + { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14 * HZ) / 10}, + { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14 * HZ) / 10}, + { "MII", 0, 0x40, XCVR_10baseT, 3 * HZ}, + { "undefined", 0, 0x01, XCVR_10baseT, 10000}, + { "Default", 0, 0xFF, XCVR_10baseT, 10000}, }; -static int vortex_scan(struct net_device *dev); -static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr, - int irq, int product_index, - int options); -static int vortex_probe1(struct net_device *dev); -static int vortex_open(struct net_device *dev); -static void vortex_timer(unsigned long arg); -static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev); -static int vortex_rx(struct net_device *dev); +static int corkscrew_scan(struct net_device *dev); +static struct net_device *corkscrew_found_device(struct net_device *dev, + int ioaddr, int irq, + int product_index, + int options); +static int corkscrew_probe1(struct net_device *dev); +static int corkscrew_open(struct net_device *dev); +static void corkscrew_timer(unsigned long arg); +static int corkscrew_start_xmit(struct sk_buff *skb, + struct net_device *dev); +static int corkscrew_rx(struct net_device *dev); +static void corkscrew_timeout(struct net_device *dev); static int boomerang_rx(struct net_device *dev); -static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs); -static int vortex_close(struct net_device *dev); +static void corkscrew_interrupt(int irq, void *dev_id, + struct pt_regs *regs); +static int corkscrew_close(struct net_device *dev); static void update_stats(int addr, struct net_device *dev); -static struct enet_statistics *vortex_get_stats(struct net_device *dev); +static struct enet_statistics *corkscrew_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); -/* Unlike the other PCI cards the 59x cards don't need a large contiguous - memory region, so making the driver a loadable module is feasible. - +/* Unfortunately maximizing the shared code between the integrated and module version of the driver results in a complicated set of initialization procedures. init_module() -- modules / tc59x_init() -- built-in - The wrappers for vortex_scan() - vortex_scan() The common routine that scans for PCI and EISA cards - vortex_found_device() Allocate a device structure when we find a card. + The wrappers for corkscrew_scan() + corkscrew_scan() The common routine that scans for PCI and EISA cards + corkscrew_found_device() Allocate a device structure when we find a card. Different versions exist for modules and built-in. - vortex_probe1() Fill in the device structure -- this is separated + corkscrew_probe1() Fill in the device structure -- this is separated so that the modules code can put it in dev->init. */ /* This driver uses 'options' to pass the media type, full-duplex flag, etc. */ /* Note: this is the only limit on the number of cards supported!! */ -static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1,}; +static int options[8] = { -1, -1, -1, -1, -1, -1, -1, -1, }; #ifdef MODULE static int debug = -1; /* A list of all installed Vortex devices, for removing the driver module. */ -static struct net_device *root_vortex_dev = NULL; +static struct net_device *root_corkscrew_dev = NULL; -int -init_module(void) +int init_module(void) { int cards_found; if (debug >= 0) - vortex_debug = debug; - if (vortex_debug) + corkscrew_debug = debug; + if (corkscrew_debug) printk(version); - root_vortex_dev = NULL; - cards_found = vortex_scan(0); + root_corkscrew_dev = NULL; + cards_found = corkscrew_scan(0); return cards_found ? 0 : -ENODEV; } @@ -403,80 +410,86 @@ int tc515_probe(struct net_device *dev) { int cards_found = 0; - cards_found = vortex_scan(dev); + cards_found = corkscrew_scan(dev); - if (vortex_debug > 0 && cards_found) + if (corkscrew_debug > 0 && cards_found) printk(version); return cards_found ? 0 : -ENODEV; } -#endif /* not MODULE */ +#endif /* not MODULE */ -static int vortex_scan(struct net_device *dev) +static int corkscrew_scan(struct net_device *dev) { int cards_found = 0; static int ioaddr = 0x100; /* Check all locations on the ISA bus -- evil! */ for (; ioaddr < 0x400; ioaddr += 0x20) { - int irq; - if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE)) - continue; - /* Check the resource configuration for a matching ioaddr. */ - if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) - continue; - /* Verify by reading the device ID from the EEPROM. */ - { - int timer; - outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); - /* Pause for at least 162 us. for the read to take place. */ - for (timer = 4; timer >= 0; timer--) { - udelay(162); - if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) == 0) - break; + int irq; + if (check_region(ioaddr, CORKSCREW_TOTAL_SIZE)) + continue; + /* Check the resource configuration for a matching ioaddr. */ + if ((inw(ioaddr + 0x2002) & 0x1f0) != (ioaddr & 0x1f0)) + continue; + /* Verify by reading the device ID from the EEPROM. */ + { + int timer; + outw(EEPROM_Read + 7, ioaddr + Wn0EepromCmd); + /* Pause for at least 162 us. for the read to take place. */ + for (timer = 4; timer >= 0; timer--) { + udelay(162); + if ((inw(ioaddr + Wn0EepromCmd) & 0x0200) + == 0) + break; + } + if (inw(ioaddr + Wn0EepromData) != 0x6d50) + continue; } - if (inw(ioaddr + Wn0EepromData) != 0x6d50) - continue; - } - printk("3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n", - inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); - irq = inw(ioaddr + 0x2002) & 15; - vortex_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev && dev->mem_start - ? dev->mem_start : options[cards_found]); - dev = 0; - cards_found++; + printk(KERN_INFO "3c515 Resource configuraiton register %#4.4x, DCR %4.4x.\n", + inl(ioaddr + 0x2002), inw(ioaddr + 0x2000)); + irq = inw(ioaddr + 0x2002) & 15; + corkscrew_found_device(dev, ioaddr, irq, CORKSCREW_ID, dev + && dev->mem_start ? dev-> + mem_start : options[cards_found]); + dev = 0; + cards_found++; } - if (vortex_debug) - printk("%d 3c515 cards found.\n", cards_found); + if (corkscrew_debug) + printk(KERN_INFO "%d 3c515 cards found.\n", cards_found); return cards_found; } -static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr, - int irq, int product_index, - int options) +static struct net_device *corkscrew_found_device(struct net_device *dev, + int ioaddr, int irq, + int product_index, + int options) { - struct vortex_private *vp; + struct corkscrew_private *vp; #ifdef MODULE /* Allocate and fill new device structure. */ int dev_size = sizeof(struct net_device) + - sizeof(struct vortex_private) + 15; /* Pad for alignment */ - + sizeof(struct corkscrew_private) + 15; /* Pad for alignment */ + dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL); memset(dev, 0, dev_size); /* Align the Rx and Tx ring entries. */ - dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15); - vp = (struct vortex_private *)dev->priv; - dev->name = vp->devname; /* An empty string. */ + dev->priv = + (void *) (((long) dev + sizeof(struct net_device) + 15) & ~15); + vp = (struct corkscrew_private *) dev->priv; + dev->name = vp->devname; /* An empty string. */ dev->base_addr = ioaddr; dev->irq = irq; - dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); - dev->init = vortex_probe1; + dev->dma = + (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); + dev->init = corkscrew_probe1; vp->product_name = "3c515"; vp->options = options; if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; + vp->media_override = + ((options & 7) == 2) ? 0 : options & 7; vp->full_duplex = (options & 8) ? 1 : 0; vp->bus_master = (options & 16) ? 1 : 0; } else { @@ -485,25 +498,28 @@ static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr vp->bus_master = 0; } ether_setup(dev); - vp->next_module = root_vortex_dev; - root_vortex_dev = dev; + vp->next_module = root_corkscrew_dev; + root_corkscrew_dev = dev; if (register_netdev(dev) != 0) return 0; -#else /* not a MODULE */ +#else /* not a MODULE */ if (dev) { /* Caution: quad-word alignment required for rings! */ - dev->priv = kmalloc(sizeof (struct vortex_private), GFP_KERNEL); - memset(dev->priv, 0, sizeof (struct vortex_private)); + dev->priv = + kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL); + memset(dev->priv, 0, sizeof(struct corkscrew_private)); } - dev = init_etherdev(dev, sizeof(struct vortex_private)); + dev = init_etherdev(dev, sizeof(struct corkscrew_private)); dev->base_addr = ioaddr; dev->irq = irq; - dev->dma = (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); - vp = (struct vortex_private *)dev->priv; + dev->dma = + (product_index == CORKSCREW_ID ? inw(ioaddr + 0x2000) & 7 : 0); + vp = (struct corkscrew_private *) dev->priv; vp->product_name = "3c515"; vp->options = options; if (options >= 0) { - vp->media_override = ((options & 7) == 2) ? 0 : options & 7; + vp->media_override = + ((options & 7) == 2) ? 0 : options & 7; vp->full_duplex = (options & 8) ? 1 : 0; vp->bus_master = (options & 16) ? 1 : 0; } else { @@ -512,25 +528,26 @@ static struct net_device *vortex_found_device(struct net_device *dev, int ioaddr vp->bus_master = 0; } - vortex_probe1(dev); -#endif /* MODULE */ + corkscrew_probe1(dev); +#endif /* MODULE */ return dev; } -static int vortex_probe1(struct net_device *dev) +static int corkscrew_probe1(struct net_device *dev) { int ioaddr = dev->base_addr; - struct vortex_private *vp = (struct vortex_private *)dev->priv; - unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; + unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ int i; - printk("%s: 3Com %s at %#3x,", dev->name, - vp->product_name, ioaddr); + printk(KERN_INFO "%s: 3Com %s at %#3x,", dev->name, + vp->product_name, ioaddr); /* Read the station address from the EEPROM. */ EL3WINDOW(0); for (i = 0; i < 0x18; i++) { - short *phys_addr = (short *)dev->dev_addr; + short *phys_addr = (short *) dev->dev_addr; int timer; outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd); /* Pause for at least 162 us. for the read to take place. */ @@ -549,97 +566,100 @@ static int vortex_probe1(struct net_device *dev) printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 6; i++) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); - if (eeprom[16] == 0x11c7) { /* Corkscrew */ - if (request_dma(dev->dma, "3c515")) { - printk(", DMA %d allocation failed", dev->dma); - dev->dma = 0; - } else - printk(", DMA %d", dev->dma); + if (eeprom[16] == 0x11c7) { /* Corkscrew */ + if (request_dma(dev->dma, "3c515")) { + printk(", DMA %d allocation failed", dev->dma); + dev->dma = 0; + } else + printk(", DMA %d", dev->dma); } printk(", IRQ %d\n", dev->irq); /* Tell them about an invalid IRQ. */ - if (vortex_debug && (dev->irq <= 0 || dev->irq > 15)) - printk(" *** Warning: this IRQ is unlikely to work! ***\n"); + if (corkscrew_debug && (dev->irq <= 0 || dev->irq > 15)) + printk(KERN_WARNING " *** Warning: this IRQ is unlikely to work! ***\n"); { - char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; + char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" }; union wn3_config config; EL3WINDOW(3); vp->available_media = inw(ioaddr + Wn3_Options); config.i = inl(ioaddr + Wn3_Config); - if (vortex_debug > 1) - printk(" Internal config register is %4.4x, transceivers %#x.\n", - config.i, inw(ioaddr + Wn3_Options)); - printk(" %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/" : "", - media_tbl[config.u.xcvr].name); + if (corkscrew_debug > 1) + printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n", + config.i, 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/" : "", + media_tbl[config.u.xcvr].name); dev->if_port = config.u.xcvr; vp->default_media = config.u.xcvr; vp->autoselect = config.u.autoselect; } if (vp->media_override != 7) { - printk(" Media override to transceiver type %d (%s).\n", - vp->media_override, media_tbl[vp->media_override].name); + printk(KERN_INFO " Media override to transceiver type %d (%s).\n", + vp->media_override, + media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } vp->capabilities = eeprom[16]; vp->full_bus_master_tx = (vp->capabilities & 0x20) ? 1 : 0; /* Rx is broken at 10mbps, so we always disable it. */ - /* vp->full_bus_master_rx = 0;*/ + /* vp->full_bus_master_rx = 0; */ vp->full_bus_master_rx = (vp->capabilities & 0x20) ? 1 : 0; /* We do a request_region() to register /proc/ioports info. */ request_region(ioaddr, CORKSCREW_TOTAL_SIZE, vp->product_name); - /* The 3c59x-specific entries in the device structure. */ - dev->open = &vortex_open; - dev->hard_start_xmit = &vortex_start_xmit; - dev->stop = &vortex_close; - dev->get_stats = &vortex_get_stats; + /* The 3c51x-specific entries in the device structure. */ + dev->open = &corkscrew_open; + dev->hard_start_xmit = &corkscrew_start_xmit; + dev->tx_timeout = &corkscrew_timeout; + dev->watchdog_timeo = (400 * HZ) / 1000; + dev->stop = &corkscrew_close; + dev->get_stats = &corkscrew_get_stats; dev->set_multicast_list = &set_rx_mode; return 0; } - -static int -vortex_open(struct net_device *dev) + +static int corkscrew_open(struct net_device *dev) { int ioaddr = dev->base_addr; - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; union wn3_config config; int i; /* Before initializing select the active media port. */ EL3WINDOW(3); if (vp->full_duplex) - outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ + outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */ config.i = inl(ioaddr + Wn3_Config); if (vp->media_override != 7) { - if (vortex_debug > 1) - printk("%s: Media override to transceiver %d (%s).\n", - dev->name, vp->media_override, - media_tbl[vp->media_override].name); + if (corkscrew_debug > 1) + printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", + dev->name, vp->media_override, + media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } else if (vp->autoselect) { /* Find first available media type, starting with 100baseTx. */ dev->if_port = 4; - while (! (vp->available_media & media_tbl[dev->if_port].mask)) + while (!(vp->available_media & media_tbl[dev->if_port].mask)) dev->if_port = media_tbl[dev->if_port].next; - if (vortex_debug > 1) + if (corkscrew_debug > 1) printk("%s: Initial media type %s.\n", - dev->name, media_tbl[dev->if_port].name); + dev->name, media_tbl[dev->if_port].name); init_timer(&vp->timer); vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); - vp->timer.data = (unsigned long)dev; - vp->timer.function = &vortex_timer; /* timer handler */ + vp->timer.data = (unsigned long) dev; + vp->timer.function = &corkscrew_timer; /* timer handler */ add_timer(&vp->timer); } else dev->if_port = vp->default_media; @@ -647,63 +667,62 @@ vortex_open(struct net_device *dev) config.u.xcvr = dev->if_port; outl(config.i, ioaddr + Wn3_Config); - if (vortex_debug > 1) { - printk("%s: vortex_open() InternalConfig %8.8x.\n", - dev->name, config.i); + if (corkscrew_debug > 1) { + printk("%s: corkscrew_open() InternalConfig %8.8x.\n", + dev->name, config.i); } outw(TxReset, ioaddr + EL3_CMD); - for (i = 20; i >= 0 ; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + for (i = 20; i >= 0; i--) + if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; outw(RxReset, ioaddr + EL3_CMD); /* Wait a few ticks for the RxReset command to complete. */ - for (i = 20; i >= 0 ; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + for (i = 20; i >= 0; i--) + if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); /* Use the now-standard shared IRQ implementation. */ if (vp->capabilities == 0x11c7) { - /* Corkscrew: Cannot share ISA resources. */ - if (dev->irq == 0 - || dev->dma == 0 - || request_irq(dev->irq, &vortex_interrupt, 0, - vp->product_name, dev)) + /* Corkscrew: Cannot share ISA resources. */ + if (dev->irq == 0 + || dev->dma == 0 + || request_irq(dev->irq, &corkscrew_interrupt, 0, + vp->product_name, dev)) return -EAGAIN; + enable_dma(dev->dma); + set_dma_mode(dev->dma, DMA_MODE_CASCADE); + } else if (request_irq(dev->irq, &corkscrew_interrupt, SA_SHIRQ, + vp->product_name, dev)) { return -EAGAIN; - enable_dma(dev->dma); - set_dma_mode(dev->dma, DMA_MODE_CASCADE); - } else if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, - vp->product_name, dev)) { - return -EAGAIN; } - if (vortex_debug > 1) { + if (corkscrew_debug > 1) { EL3WINDOW(4); - printk("%s: vortex_open() irq %d media status %4.4x.\n", - dev->name, dev->irq, inw(ioaddr + Wn4_Media)); + printk("%s: corkscrew_open() irq %d media status %4.4x.\n", + dev->name, dev->irq, inw(ioaddr + Wn4_Media)); } /* Set the station address and mask in window 2 each time opened. */ EL3WINDOW(2); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + i); - for (; i < 12; i+=2) + for (; i < 12; i += 2) outw(0, ioaddr + i); if (dev->if_port == 3) - /* Start the thinnet transceiver. We should really wait 50ms...*/ + /* Start the thinnet transceiver. We should really wait 50ms... */ outw(StartCoax, ioaddr + EL3_CMD); EL3WINDOW(4); - outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | - media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP | Media_SQE)) | + media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); /* Switch to the stats window, and clear all stats by reading. */ outw(StatsDisable, ioaddr + EL3_CMD); EL3WINDOW(6); - for (i = 0; i < 10; i++) + for (i = 0; i < 10; i++) inb(ioaddr + i); inw(ioaddr + 10); inw(ioaddr + 12); @@ -716,32 +735,34 @@ vortex_open(struct net_device *dev) /* Switch to register set 7 for normal use. */ EL3WINDOW(7); - if (vp->full_bus_master_rx) { /* Boomerang bus master. */ + if (vp->full_bus_master_rx) { /* Boomerang bus master. */ vp->cur_rx = vp->dirty_rx = 0; - if (vortex_debug > 2) - printk("%s: Filling in the Rx ring.\n", dev->name); + if (corkscrew_debug > 2) + printk("%s: Filling in the Rx ring.\n", + dev->name); for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; if (i < (RX_RING_SIZE - 1)) - vp->rx_ring[i].next = virt_to_bus(&vp->rx_ring[i+1]); + vp->rx_ring[i].next = + virt_to_bus(&vp->rx_ring[i + 1]); else - vp->rx_ring[i].next = 0; + vp->rx_ring[i].next = 0; vp->rx_ring[i].status = 0; /* Clear complete bit. */ vp->rx_ring[i].length = PKT_BUF_SZ | 0x80000000; skb = dev_alloc_skb(PKT_BUF_SZ); vp->rx_skbuff[i] = skb; if (skb == NULL) - break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ + 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[i].addr = virt_to_bus(skb->tail); } - vp->rx_ring[i-1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ + vp->rx_ring[i - 1].next = virt_to_bus(&vp->rx_ring[0]); /* Wrap the ring. */ outl(virt_to_bus(&vp->rx_ring[0]), ioaddr + UpListPtr); } - if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ + if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ vp->cur_tx = vp->dirty_tx = 0; - outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); /* Room for a packet. */ + outb(PKT_BUF_SZ >> 8, ioaddr + TxFreeThreshold); /* Room for a packet. */ /* Clear the Tx ring. */ for (i = 0; i < TX_RING_SIZE; i++) vp->tx_skbuff[i] = 0; @@ -749,175 +770,188 @@ vortex_open(struct net_device *dev) } /* Set receiver mode: presumably accept b-case and phys addr only. */ set_rx_mode(dev); - outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ + outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; + netif_start_queue(dev); - outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ - outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ + outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ + outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ - outw(SetStatusEnb | AdapterFailure|IntReq|StatsFull | - (vp->full_bus_master_tx ? DownComplete : TxAvailable) | - (vp->full_bus_master_rx ? UpComplete : RxComplete) | - (vp->bus_master ? DMADone : 0), - ioaddr + EL3_CMD); + outw(SetStatusEnb | AdapterFailure | IntReq | StatsFull | + (vp->full_bus_master_tx ? DownComplete : TxAvailable) | + (vp->full_bus_master_rx ? UpComplete : RxComplete) | + (vp->bus_master ? DMADone : 0), ioaddr + EL3_CMD); /* Ack all pending events, and set active indicator mask. */ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, - ioaddr + EL3_CMD); + ioaddr + EL3_CMD); outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull - | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete, - ioaddr + EL3_CMD); + | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete, + ioaddr + EL3_CMD); MOD_INC_USE_COUNT; return 0; } -static void vortex_timer(unsigned long data) +static void corkscrew_timer(unsigned long data) { #ifdef AUTOMEDIA - struct net_device *dev = (struct net_device *)data; - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct net_device *dev = (struct net_device *) data; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; int ioaddr = dev->base_addr; unsigned long flags; int ok = 0; - if (vortex_debug > 1) + if (corkscrew_debug > 1) printk("%s: Media selection timer tick happened, %s.\n", - dev->name, media_tbl[dev->if_port].name); - - save_flags(flags); cli(); { - int old_window = inw(ioaddr + EL3_CMD) >> 13; - int media_status; - EL3WINDOW(4); - media_status = inw(ioaddr + Wn4_Media); - switch (dev->if_port) { - case 0: case 4: case 5: /* 10baseT, 100baseTX, 100baseFX */ - if (media_status & Media_LnkBeat) { - ok = 1; - if (vortex_debug > 1) - printk("%s: Media %s has link beat, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - } else if (vortex_debug > 1) - printk("%s: Media %s is has no link beat, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - - break; - default: /* Other media types handled by Tx timeouts. */ - if (vortex_debug > 1) - printk("%s: Media %s is has no indication, %x.\n", - dev->name, media_tbl[dev->if_port].name, media_status); - ok = 1; - } - if ( ! ok) { - union wn3_config config; + dev->name, media_tbl[dev->if_port].name); - do { - dev->if_port = media_tbl[dev->if_port].next; - } while ( ! (vp->available_media & media_tbl[dev->if_port].mask)); - if (dev->if_port == 8) { /* Go back to default. */ - dev->if_port = vp->default_media; - if (vortex_debug > 1) - printk("%s: Media selection failing, using default %s port.\n", - dev->name, media_tbl[dev->if_port].name); - } else { - if (vortex_debug > 1) - printk("%s: Media selection failed, now trying %s port.\n", - dev->name, media_tbl[dev->if_port].name); - vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); - add_timer(&vp->timer); + save_flags(flags); + cli(); { + int old_window = inw(ioaddr + EL3_CMD) >> 13; + int media_status; + EL3WINDOW(4); + media_status = inw(ioaddr + Wn4_Media); + switch (dev->if_port) { + case 0: + case 4: + case 5: /* 10baseT, 100baseTX, 100baseFX */ + if (media_status & Media_LnkBeat) { + ok = 1; + if (corkscrew_debug > 1) + printk("%s: Media %s has link beat, %x.\n", + dev->name, + media_tbl[dev->if_port].name, + media_status); + } else if (corkscrew_debug > 1) + printk("%s: Media %s is has no link beat, %x.\n", + dev->name, + media_tbl[dev->if_port].name, + media_status); + + break; + default: /* Other media types handled by Tx timeouts. */ + if (corkscrew_debug > 1) + printk("%s: Media %s is has no indication, %x.\n", + dev->name, + media_tbl[dev->if_port].name, + media_status); + ok = 1; } - outw((media_status & ~(Media_10TP|Media_SQE)) | - media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); + if (!ok) { + union wn3_config config; - EL3WINDOW(3); - config.i = inl(ioaddr + Wn3_Config); - config.u.xcvr = dev->if_port; - outl(config.i, ioaddr + Wn3_Config); - - outw(dev->if_port == 3 ? StartCoax : StopCoax, ioaddr + EL3_CMD); - } - EL3WINDOW(old_window); - } restore_flags(flags); - if (vortex_debug > 1) - printk("%s: Media selection timer finished, %s.\n", - dev->name, media_tbl[dev->if_port].name); - -#endif /* AUTOMEDIA*/ + do { + dev->if_port = + media_tbl[dev->if_port].next; + } + while (!(vp->available_media & media_tbl[dev->if_port].mask)); + + if (dev->if_port == 8) { /* Go back to default. */ + dev->if_port = vp->default_media; + if (corkscrew_debug > 1) + printk("%s: Media selection failing, using default %s port.\n", + dev->name, + media_tbl[dev->if_port].name); + } else { + if (corkscrew_debug > 1) + printk("%s: Media selection failed, now trying %s port.\n", + dev->name, + media_tbl[dev->if_port].name); + vp->timer.expires = RUN_AT(media_tbl[dev->if_port].wait); + add_timer(&vp->timer); + } + outw((media_status & ~(Media_10TP | Media_SQE)) | + 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); + + outw(dev->if_port == 3 ? StartCoax : StopCoax, + ioaddr + EL3_CMD); + } + EL3WINDOW(old_window); + } + restore_flags(flags); + if (corkscrew_debug > 1) + printk("%s: Media selection timer finished, %s.\n", + dev->name, media_tbl[dev->if_port].name); + +#endif /* AUTOMEDIA */ return; } -static int -vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) +static void corkscrew_timeout(struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + int i; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; int ioaddr = dev->base_addr; - if (dev->tbusy) { - int tickssofar = jiffies - dev->trans_start; - int i; - - /* Min. wait before assuming a Tx failed == 400ms. */ - - if (tickssofar < 400*HZ/1000) /* We probably aren't empty. */ - return 1; - printk("%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("%s: Transmitter encountered 16 collisions -- network" - " network cable problem?\n", dev->name); + printk(KERN_WARNING + "%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_WARNING + "%s: Transmitter encountered 16 collisions -- network" + " network cable problem?\n", dev->name); #ifndef final_version - printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n", - vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, vp->cur_tx); - printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), - &vp->tx_ring[0]); - for (i = 0; i < TX_RING_SIZE; i++) { - printk(" %d: %p length %8.8x status %8.8x\n", i, - &vp->tx_ring[i], - vp->tx_ring[i].length, - vp->tx_ring[i].status); - } -#endif - /* Issue TX_RESET and TX_START commands. */ - outw(TxReset, ioaddr + EL3_CMD); - for (i = 20; i >= 0 ; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) - break; - outw(TxEnable, ioaddr + EL3_CMD); - dev->trans_start = jiffies; - /* dev->tbusy = 0;*/ - vp->stats.tx_errors++; - vp->stats.tx_dropped++; - return 0; /* Yes, silently *drop* the packet! */ + printk(" Flags; bus-master %d, full %d; dirty %d current %d.\n", + vp->full_bus_master_tx, vp->tx_full, vp->dirty_tx, + vp->cur_tx); + printk(" Down list %8.8x vs. %p.\n", inl(ioaddr + DownListPtr), + &vp->tx_ring[0]); + for (i = 0; i < TX_RING_SIZE; i++) { + printk(" %d: %p length %8.8x status %8.8x\n", i, + &vp->tx_ring[i], + vp->tx_ring[i].length, vp->tx_ring[i].status); } +#endif + /* Issue TX_RESET and TX_START commands. */ + outw(TxReset, ioaddr + EL3_CMD); + for (i = 20; i >= 0; i--) + if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) + break; + outw(TxEnable, ioaddr + EL3_CMD); + dev->trans_start = jiffies; + vp->stats.tx_errors++; + vp->stats.tx_dropped++; + netif_wake_queue(dev); +} - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - If this ever occurs the queue layer is doing something evil! */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } +static int corkscrew_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; + int ioaddr = dev->base_addr; + + /* Block a timer-based transmit from overlapping. */ - if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */ + netif_stop_queue(dev); + + if (vp->full_bus_master_tx) { /* BOOMERANG bus-master */ /* Calculate the next Tx descriptor entry. */ int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry; unsigned long flags, i; - if (vp->tx_full) /* No room to transmit with */ - return 1; + if (vp->tx_full) /* No room to transmit with */ + return 1; if (vp->cur_tx != 0) - prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; + prev_entry = + &vp->tx_ring[(vp->cur_tx - 1) % TX_RING_SIZE]; else - prev_entry = NULL; - if (vortex_debug > 3) + prev_entry = NULL; + if (corkscrew_debug > 3) printk("%s: Trying to send a packet, Tx index %d.\n", - dev->name, vp->cur_tx); + dev->name, vp->cur_tx); /* vp->tx_full = 1; */ vp->tx_skbuff[entry] = skb; vp->tx_ring[entry].next = 0; @@ -929,13 +963,15 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) cli(); outw(DownStall, ioaddr + EL3_CMD); /* Wait for the stall to complete. */ - for (i = 20; i >= 0 ; i--) - if ( (inw(ioaddr + EL3_STATUS) & CmdInProgress) == 0) - break; + for (i = 20; i >= 0; i--) + if ((inw(ioaddr + EL3_STATUS) & CmdInProgress) == + 0) break; if (prev_entry) - prev_entry->next = virt_to_bus(&vp->tx_ring[entry]); + prev_entry->next = + virt_to_bus(&vp->tx_ring[entry]); if (inl(ioaddr + DownListPtr) == 0) { - outl(virt_to_bus(&vp->tx_ring[entry]), ioaddr + DownListPtr); + outl(virt_to_bus(&vp->tx_ring[entry]), + ioaddr + DownListPtr); queued_packet++; } outw(DownUnstall, ioaddr + EL3_CMD); @@ -944,10 +980,10 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) vp->cur_tx++; if (vp->cur_tx - vp->dirty_tx > TX_RING_SIZE - 1) vp->tx_full = 1; - else { /* Clear previous interrupt enable. */ - if (prev_entry) - prev_entry->status &= ~0x80000000; - dev->tbusy = 0; + else { /* Clear previous interrupt enable. */ + if (prev_entry) + prev_entry->status &= ~0x80000000; + netif_wake_queue(dev); } dev->trans_start = jiffies; return 0; @@ -957,31 +993,32 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) #ifdef VORTEX_BUS_MASTER if (vp->bus_master) { /* Set the bus-master controller to transfer the packet. */ - outl((int)(skb->data), ioaddr + Wn7_MasterAddr); + outl((int) (skb->data), ioaddr + Wn7_MasterAddr); outw((skb->len + 3) & ~3, ioaddr + Wn7_MasterLen); vp->tx_skb = skb; outw(StartDMADown, ioaddr + EL3_CMD); - /* dev->tbusy will be cleared at the DMADone interrupt. */ + /* queue will be woken at the DMADone interrupt. */ } else { /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev_kfree_skb (skb); + dev_kfree_skb(skb); if (inw(ioaddr + TxFree) > 1536) { - dev->tbusy = 0; + netif_wake_queue(dev); } else /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); + outw(SetTxThreshold + (1536 >> 2), + ioaddr + EL3_CMD); } #else /* ... and the packet rounded to a doubleword. */ outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - dev_kfree_skb (skb); + dev_kfree_skb(skb); if (inw(ioaddr + TxFree) > 1536) { - dev->tbusy = 0; + netif_wake_queue(dev); } else /* Interrupt us when the FIFO has room for max-sized packet. */ - outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); -#endif /* bus master */ + outw(SetTxThreshold + (1536 >> 2), ioaddr + EL3_CMD); +#endif /* bus master */ dev->trans_start = jiffies; @@ -990,80 +1027,80 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev) short tx_status; int i = 4; - while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { - if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ - if (vortex_debug > 2) - printk("%s: Tx error, status %2.2x.\n", - dev->name, tx_status); - if (tx_status & 0x04) vp->stats.tx_fifo_errors++; - if (tx_status & 0x38) vp->stats.tx_aborted_errors++; + while (--i > 0 && (tx_status = inb(ioaddr + TxStatus)) > 0) { + if (tx_status & 0x3C) { /* A Tx-disabling error occurred. */ + if (corkscrew_debug > 2) + printk("%s: Tx error, status %2.2x.\n", + dev->name, tx_status); + if (tx_status & 0x04) + vp->stats.tx_fifo_errors++; + if (tx_status & 0x38) + vp->stats.tx_aborted_errors++; if (tx_status & 0x30) { int j; outw(TxReset, ioaddr + EL3_CMD); - for (j = 20; j >= 0 ; j--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + for (j = 20; j >= 0; j--) + if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; } outw(TxEnable, ioaddr + EL3_CMD); } - outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ + outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ } } - vp->stats.tx_bytes+=skb->len; + vp->stats.tx_bytes += skb->len; return 0; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ -static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs) + +static void corkscrew_interrupt(int irq, void *dev_id, + struct pt_regs *regs) { /* Use the now-standard shared IRQ implementation. */ struct net_device *dev = dev_id; - struct vortex_private *lp; + struct corkscrew_private *lp; int ioaddr, status; int latency; int i = max_interrupt_work; - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk("%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - ioaddr = dev->base_addr; latency = inb(ioaddr + Timer); - lp = (struct vortex_private *)dev->priv; + lp = (struct corkscrew_private *) dev->priv; status = inw(ioaddr + EL3_STATUS); - if (vortex_debug > 4) - printk("%s: interrupt, status %4.4x, timer %d.\n", dev->name, - status, latency); + if (corkscrew_debug > 4) + printk("%s: interrupt, status %4.4x, timer %d.\n", + dev->name, status, latency); if ((status & 0xE000) != 0xE000) { - static int donedidthis=0; + static int donedidthis = 0; /* Some interrupt controllers store a bogus interrupt from boot-time. Ignore a single early interrupt, but don't hang the machine for other interrupt problems. */ if (donedidthis++ > 100) { - printk("%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", - dev->name, status, dev->start); - FREE_IRQ(dev->irq, dev); + printk(KERN_ERR "%s: Bogus interrupt, bailing. Status %4.4x, start=%d.\n", + dev->name, status, + test_bit(LINK_STATE_START, &dev->state)); + free_irq(dev->irq, dev); } } do { - if (vortex_debug > 5) - printk("%s: In interrupt loop, status %4.4x.\n", - dev->name, status); + if (corkscrew_debug > 5) + printk("%s: In interrupt loop, status %4.4x.\n", + dev->name, status); if (status & RxComplete) - vortex_rx(dev); + corkscrew_rx(dev); if (status & TxAvailable) { - if (vortex_debug > 5) - printk(" TX room bit was handled.\n"); + if (corkscrew_debug > 5) + printk + (" TX room bit was handled.\n"); /* There's room in the FIFO for a full-sized packet. */ outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } if (status & DownComplete) { unsigned int dirty_tx = lp->dirty_tx; @@ -1071,28 +1108,29 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs) while (lp->cur_tx - dirty_tx > 0) { int entry = dirty_tx % TX_RING_SIZE; if (inl(ioaddr + DownListPtr) == - virt_to_bus(&lp->tx_ring[entry])) - break; /* It still hasn't been processed. */ + virt_to_bus(&lp->tx_ring[entry])) + break; /* It still hasn't been processed. */ if (lp->tx_skbuff[entry]) { - dev_kfree_skb_irq(lp->tx_skbuff[entry]); + dev_kfree_skb_irq(lp-> + tx_skbuff + [entry]); lp->tx_skbuff[entry] = 0; } dirty_tx++; } lp->dirty_tx = dirty_tx; outw(AckIntr | DownComplete, ioaddr + EL3_CMD); - if (lp->tx_full && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) { - lp->tx_full= 0; - dev->tbusy = 0; - mark_bh(NET_BH); + if (lp->tx_full + && (lp->cur_tx - dirty_tx <= TX_RING_SIZE - 1)) { + lp->tx_full = 0; + netif_wake_queue(dev); } } #ifdef VORTEX_BUS_MASTER if (status & DMADone) { - outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ - dev->tbusy = 0; - dev_kfree_skb_irq (lp->tx_skb); /* Release the transfered buffer */ - mark_bh(NET_BH); + outw(0x1000, ioaddr + Wn7_MasterStatus); /* Ack the event. */ + dev_kfree_skb_irq(lp->tx_skb); /* Release the transfered buffer */ + netif_wake_queue(dev); } #endif if (status & UpComplete) { @@ -1101,32 +1139,36 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs) } if (status & (AdapterFailure | RxEarly | StatsFull)) { /* Handle all uncommon interrupts at once. */ - if (status & RxEarly) { /* Rx early is unused. */ - vortex_rx(dev); + if (status & RxEarly) { /* Rx early is unused. */ + corkscrew_rx(dev); outw(AckIntr | RxEarly, ioaddr + EL3_CMD); } - if (status & StatsFull) { /* Empty statistics. */ + if (status & StatsFull) { /* Empty statistics. */ static int DoneDidThat = 0; - if (vortex_debug > 4) - printk("%s: Updating stats.\n", dev->name); + if (corkscrew_debug > 4) + printk("%s: Updating stats.\n", + dev->name); update_stats(ioaddr, dev); /* DEBUG HACK: Disable statistics as an interrupt source. */ /* This occurs when we have the wrong media type! */ - if (DoneDidThat == 0 && - inw(ioaddr + EL3_STATUS) & StatsFull) { + if (DoneDidThat == 0 && + inw(ioaddr + EL3_STATUS) & StatsFull) { int win, reg; printk("%s: Updating stats failed, disabling stats as an" - " interrupt source.\n", dev->name); + " interrupt source.\n", + dev->name); for (win = 0; win < 8; win++) { EL3WINDOW(win); printk("\n Vortex window %d:", win); for (reg = 0; reg < 16; reg++) - printk(" %2.2x", inb(ioaddr+reg)); + printk(" %2.2x", + inb(ioaddr + reg)); } EL3WINDOW(7); - outw(SetIntrEnb | TxAvailable | RxComplete | AdapterFailure - | UpComplete | DownComplete | TxComplete, - ioaddr + EL3_CMD); + outw(SetIntrEnb | TxAvailable | + RxComplete | AdapterFailure | + UpComplete | DownComplete | + TxComplete, ioaddr + EL3_CMD); DoneDidThat++; } } @@ -1135,139 +1177,150 @@ static void vortex_interrupt IRQ(int irq, void *dev_id, struct pt_regs *regs) outw(RxReset, ioaddr + EL3_CMD); /* Set the Rx filter to the current state. */ set_rx_mode(dev); - outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ - outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); + outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */ + outw(AckIntr | AdapterFailure, + ioaddr + EL3_CMD); } } if (--i < 0) { - printk("%s: Too much work in interrupt, status %4.4x. " - "Disabling functions (%4.4x).\n", - dev->name, status, SetStatusEnb | ((~status) & 0x7FE)); + printk(KERN_ERR "%s: Too much work in interrupt, status %4.4x. " + "Disabling functions (%4.4x).\n", dev->name, + status, SetStatusEnb | ((~status) & 0x7FE)); /* Disable all pending interrupts. */ - outw(SetStatusEnb | ((~status) & 0x7FE), ioaddr + EL3_CMD); + outw(SetStatusEnb | ((~status) & 0x7FE), + ioaddr + EL3_CMD); outw(AckIntr | 0x7FF, ioaddr + EL3_CMD); break; } /* Acknowledge the IRQ. */ outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); - } while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete)); + } while ((status = inw(ioaddr + EL3_STATUS)) & + (IntLatch | RxComplete)); - if (vortex_debug > 4) - printk("%s: exiting interrupt, status %4.4x.\n", dev->name, status); - - dev->interrupt = 0; - return; + if (corkscrew_debug > 4) + printk("%s: exiting interrupt, status %4.4x.\n", dev->name, + status); } -static int -vortex_rx(struct net_device *dev) +static int corkscrew_rx(struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv; int ioaddr = dev->base_addr; int i; short rx_status; - if (vortex_debug > 5) + if (corkscrew_debug > 5) printk(" In rx_packet(), status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus)); while ((rx_status = inw(ioaddr + RxStatus)) > 0) { - if (rx_status & 0x4000) { /* Error, update stats. */ + if (rx_status & 0x4000) { /* Error, update stats. */ unsigned char rx_error = inb(ioaddr + RxErrors); - if (vortex_debug > 2) - printk(" Rx error: status %2.2x.\n", rx_error); + if (corkscrew_debug > 2) + printk(" Rx error: status %2.2x.\n", + rx_error); vp->stats.rx_errors++; - if (rx_error & 0x01) vp->stats.rx_over_errors++; - if (rx_error & 0x02) vp->stats.rx_length_errors++; - if (rx_error & 0x04) vp->stats.rx_frame_errors++; - if (rx_error & 0x08) vp->stats.rx_crc_errors++; - if (rx_error & 0x10) vp->stats.rx_length_errors++; + if (rx_error & 0x01) + vp->stats.rx_over_errors++; + if (rx_error & 0x02) + vp->stats.rx_length_errors++; + if (rx_error & 0x04) + vp->stats.rx_frame_errors++; + if (rx_error & 0x08) + vp->stats.rx_crc_errors++; + if (rx_error & 0x10) + vp->stats.rx_length_errors++; } else { /* The packet length: up to 4.5K!. */ short pkt_len = rx_status & 0x1fff; struct sk_buff *skb; - skb = DEV_ALLOC_SKB(pkt_len + 5); - if (vortex_debug > 4) + skb = dev_alloc_skb(pkt_len + 5 + 2); + if (corkscrew_debug > 4) printk("Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); + pkt_len, rx_status); if (skb != NULL) { skb->dev = dev; skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ /* 'skb_put()' points to the start of sk_buff data area. */ - insl(ioaddr + RX_FIFO, skb_put(skb, pkt_len), - (pkt_len + 3) >> 2); - outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ + insl(ioaddr + RX_FIFO, + skb_put(skb, pkt_len), + (pkt_len + 3) >> 2); + outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; vp->stats.rx_packets++; - vp->stats.rx_bytes+=skb->len; + vp->stats.rx_bytes += skb->len; /* Wait a limited time to go to next packet. */ for (i = 200; i >= 0; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; continue; - } else if (vortex_debug) - printk("%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); + } else if (corkscrew_debug) + printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); } outw(RxDiscard, ioaddr + EL3_CMD); vp->stats.rx_dropped++; /* Wait a limited time to skip this packet. */ for (i = 200; i >= 0; i--) - if ( ! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) + if (!(inw(ioaddr + EL3_STATUS) & CmdInProgress)) break; } - return 0; } -static int -boomerang_rx(struct net_device *dev) +static int boomerang_rx(struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; int entry = vp->cur_rx % RX_RING_SIZE; int ioaddr = dev->base_addr; int rx_status; - if (vortex_debug > 5) + if (corkscrew_debug > 5) printk(" In boomerang_rx(), status %4.4x, rx_status %4.4x.\n", - inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); + inw(ioaddr + EL3_STATUS), inw(ioaddr + RxStatus)); while ((rx_status = vp->rx_ring[entry].status) & RxDComplete) { - if (rx_status & RxDError) { /* Error, update stats. */ + if (rx_status & RxDError) { /* Error, update stats. */ unsigned char rx_error = rx_status >> 16; - if (vortex_debug > 2) - printk(" Rx error: status %2.2x.\n", rx_error); + if (corkscrew_debug > 2) + printk(" Rx error: status %2.2x.\n", + rx_error); vp->stats.rx_errors++; - if (rx_error & 0x01) vp->stats.rx_over_errors++; - if (rx_error & 0x02) vp->stats.rx_length_errors++; - if (rx_error & 0x04) vp->stats.rx_frame_errors++; - if (rx_error & 0x08) vp->stats.rx_crc_errors++; - if (rx_error & 0x10) vp->stats.rx_length_errors++; + if (rx_error & 0x01) + vp->stats.rx_over_errors++; + if (rx_error & 0x02) + vp->stats.rx_length_errors++; + if (rx_error & 0x04) + vp->stats.rx_frame_errors++; + if (rx_error & 0x08) + vp->stats.rx_crc_errors++; + if (rx_error & 0x10) + vp->stats.rx_length_errors++; } else { /* The packet length: up to 4.5K!. */ short pkt_len = rx_status & 0x1fff; struct sk_buff *skb; - vp->stats.rx_bytes+=pkt_len; - if (vortex_debug > 4) + vp->stats.rx_bytes += pkt_len; + if (corkscrew_debug > 4) printk("Receiving packet size %d status %4.4x.\n", - pkt_len, rx_status); + pkt_len, rx_status); /* 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) { + && (skb = dev_alloc_skb(pkt_len + 4)) != 0) { skb->dev = dev; skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ /* 'skb_put()' points to the start of sk_buff data area. */ memcpy(skb_put(skb, pkt_len), - bus_to_virt(vp->rx_ring[entry].addr), - pkt_len); + bus_to_virt(vp->rx_ring[entry]. + addr), pkt_len); rx_copy++; - } else{ + } else { void *temp; /* Pass up the skbuff already on the Rx ring. */ skb = vp->rx_skbuff[entry]; @@ -1275,10 +1328,13 @@ boomerang_rx(struct net_device *dev) temp = skb_put(skb, pkt_len); /* Remove this checking code for final release. */ if (bus_to_virt(vp->rx_ring[entry].addr) != temp) - printk("%s: Warning -- the skbuff addresses do not match" - " in boomerang_rx: %p vs. %p / %p.\n", dev->name, - bus_to_virt(vp->rx_ring[entry].addr), - skb->head, temp); + printk("%s: Warning -- the skbuff addresses do not match" + " in boomerang_rx: %p vs. %p / %p.\n", + dev->name, + bus_to_virt(vp-> + rx_ring[entry]. + addr), skb->head, + temp); rx_nocopy++; } skb->protocol = eth_type_trans(skb, dev); @@ -1295,8 +1351,8 @@ boomerang_rx(struct net_device *dev) if (vp->rx_skbuff[entry] == NULL) { skb = dev_alloc_skb(PKT_BUF_SZ); if (skb == NULL) - break; /* Bad news! */ - skb->dev = dev; /* Mark as being used by this device. */ + 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 = virt_to_bus(skb->tail); vp->rx_skbuff[entry] = skb; @@ -1306,22 +1362,22 @@ boomerang_rx(struct net_device *dev) return 0; } -static int -vortex_close(struct net_device *dev) +static int corkscrew_close(struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; int ioaddr = dev->base_addr; int i; - dev->start = 0; - dev->tbusy = 1; + netif_stop_queue(dev); - if (vortex_debug > 1) { - printk("%s: vortex_close() status %4.4x, Tx status %2.2x.\n", - dev->name, inw(ioaddr + EL3_STATUS), inb(ioaddr + TxStatus)); - printk("%s: vortex close stats: rx_nocopy %d rx_copy %d" - " tx_queued %d.\n", - dev->name, rx_nocopy, rx_copy, queued_packet); + if (corkscrew_debug > 1) { + printk("%s: corkscrew_close() status %4.4x, Tx status %2.2x.\n", + dev->name, inw(ioaddr + EL3_STATUS), + inb(ioaddr + TxStatus)); + printk("%s: corkscrew close stats: rx_nocopy %d rx_copy %d" + " tx_queued %d.\n", dev->name, rx_nocopy, rx_copy, + queued_packet); } del_timer(&vp->timer); @@ -1337,28 +1393,20 @@ vortex_close(struct net_device *dev) /* Turn off thinnet power. Green! */ outw(StopCoax, ioaddr + EL3_CMD); -#ifdef SA_SHIRQ free_irq(dev->irq, dev); -#else - free_irq(dev->irq); - irq2dev_map[dev->irq] = 0; -#endif outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); update_stats(ioaddr, dev); - if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ + if (vp->full_bus_master_rx) { /* Free Boomerang bus master Rx buffers. */ outl(0, ioaddr + UpListPtr); for (i = 0; i < RX_RING_SIZE; i++) if (vp->rx_skbuff[i]) { -#if LINUX_VERSION_CODE < 0x20100 - vp->rx_skbuff[i]->free = 1; -#endif - dev_kfree_skb (vp->rx_skbuff[i]); + dev_kfree_skb(vp->rx_skbuff[i]); vp->rx_skbuff[i] = 0; } } - if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ + if (vp->full_bus_master_tx) { /* Free Boomerang bus master Tx buffers. */ outl(0, ioaddr + DownListPtr); for (i = 0; i < TX_RING_SIZE; i++) if (vp->tx_skbuff[i]) { @@ -1372,13 +1420,13 @@ vortex_close(struct net_device *dev) return 0; } -static struct enet_statistics * -vortex_get_stats(struct net_device *dev) +static struct enet_statistics *corkscrew_get_stats(struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; unsigned long flags; - if (dev->start) { + if (test_bit(LINK_STATE_START, &dev->state)) { save_flags(flags); cli(); update_stats(dev->base_addr, dev); @@ -1396,21 +1444,23 @@ vortex_get_stats(struct net_device *dev) */ static void update_stats(int ioaddr, struct net_device *dev) { - struct vortex_private *vp = (struct vortex_private *)dev->priv; + struct corkscrew_private *vp = + (struct corkscrew_private *) dev->priv; /* Unlike the 3c5x9 we need not turn off stats updates while reading. */ /* Switch to the stats window, and read everything. */ EL3WINDOW(6); - vp->stats.tx_carrier_errors += inb(ioaddr + 0); - vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); - /* Multiple collisions. */ inb(ioaddr + 2); - vp->stats.collisions += inb(ioaddr + 3); - vp->stats.tx_window_errors += inb(ioaddr + 4); - vp->stats.rx_fifo_errors += inb(ioaddr + 5); - vp->stats.tx_packets += inb(ioaddr + 6); - vp->stats.tx_packets += (inb(ioaddr + 9)&0x30) << 4; - /* Rx packets */ inb(ioaddr + 7); /* Must read to clear */ - /* Tx deferrals */ inb(ioaddr + 8); + vp->stats.tx_carrier_errors += inb(ioaddr + 0); + vp->stats.tx_heartbeat_errors += inb(ioaddr + 1); + /* Multiple collisions. */ inb(ioaddr + 2); + vp->stats.collisions += inb(ioaddr + 3); + vp->stats.tx_window_errors += inb(ioaddr + 4); + vp->stats.rx_fifo_errors += inb(ioaddr + 5); + vp->stats.tx_packets += inb(ioaddr + 6); + vp->stats.tx_packets += (inb(ioaddr + 9) & 0x30) << 4; + /* Rx packets */ inb(ioaddr + 7); + /* Must read to clear */ + /* Tx deferrals */ inb(ioaddr + 8); /* Don't bother with register 9, an extension of registers 6&7. If we do use the 6&7 values the atomic update assumption above is invalid. */ @@ -1429,18 +1479,18 @@ static void update_stats(int ioaddr, struct net_device *dev) The Vortex chip has no documented multicast filter, so the only multicast setting is to receive all multicast frames. At least the chip has a very clean way to set the mode, unlike many others. */ -static void -set_rx_mode(struct net_device *dev) +static void set_rx_mode(struct net_device *dev) { int ioaddr = dev->base_addr; short new_mode; if (dev->flags & IFF_PROMISC) { - if (vortex_debug > 3) - printk("%s: Setting promiscuous mode.\n", dev->name); - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast|RxProm; - } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { - new_mode = SetRxFilter|RxStation|RxMulticast|RxBroadcast; + if (corkscrew_debug > 3) + printk("%s: Setting promiscuous mode.\n", + dev->name); + new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm; + } else if ((dev->mc_list) || (dev->flags & IFF_ALLMULTI)) { + new_mode = SetRxFilter | RxStation | RxMulticast | RxBroadcast; } else new_mode = SetRxFilter | RxStation | RxBroadcast; @@ -1448,24 +1498,26 @@ set_rx_mode(struct net_device *dev) } #ifdef MODULE -void -cleanup_module(void) +void cleanup_module(void) { struct net_device *next_dev; /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ - while (root_vortex_dev) { - next_dev = ((struct vortex_private *)root_vortex_dev->priv)->next_module; - if (root_vortex_dev->dma) - free_dma(root_vortex_dev->dma); - unregister_netdev(root_vortex_dev); - outw(TotalReset, root_vortex_dev->base_addr + EL3_CMD); - release_region(root_vortex_dev->base_addr, CORKSCREW_TOTAL_SIZE); - kfree(root_vortex_dev); - root_vortex_dev = next_dev; + while (root_corkscrew_dev) { + next_dev = + ((struct corkscrew_private *) root_corkscrew_dev-> + priv)->next_module; + if (root_corkscrew_dev->dma) + free_dma(root_corkscrew_dev->dma); + unregister_netdev(root_corkscrew_dev); + outw(TotalReset, root_corkscrew_dev->base_addr + EL3_CMD); + release_region(root_corkscrew_dev->base_addr, + CORKSCREW_TOTAL_SIZE); + kfree(root_corkscrew_dev); + root_corkscrew_dev = next_dev; } } -#endif /* MODULE */ +#endif /* MODULE */ /* * Local variables: diff --git a/drivers/net/cops.c b/drivers/net/cops.c index c15a1937c017..466705f9edac 100644 --- a/drivers/net/cops.c +++ b/drivers/net/cops.c @@ -30,6 +30,7 @@ * cleanup of formatting and program * logic. Added emacs 'local-vars' * setup for Jay's brace style. + * 20000211 Alan Cox Cleaned up for softnet */ static const char *version = @@ -48,10 +49,8 @@ static const char *version = */ #include -#ifdef MODULE #include #include -#endif #include #include @@ -180,7 +179,7 @@ static unsigned int cops_debug = COPS_DEBUG; struct cops_local { - struct enet_statistics stats; + struct net_device_stats stats; int board; /* Holds what board type is. */ int nodeid; /* Set to 1 once have nodeid. */ unsigned char node_acquire; /* Node ID when acquired. */ @@ -200,6 +199,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid); static void cops_interrupt (int irq, void *dev_id, struct pt_regs *regs); static void cops_poll (unsigned long ltdev); +static void cops_timeout(struct net_device *dev); static void cops_rx (struct net_device *dev); static int cops_send_packet (struct sk_buff *skb, struct net_device *dev); static void set_multicast_list (struct net_device *dev); @@ -209,7 +209,7 @@ static int cops_hard_header (struct sk_buff *skb, struct net_device *dev, static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); static int cops_close (struct net_device *dev); -static struct enet_statistics *cops_get_stats (struct net_device *dev); +static struct net_device_stats *cops_get_stats (struct net_device *dev); /* @@ -323,13 +323,15 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) /* Fill in the fields of the device structure with LocalTalk values. */ ltalk_setup(dev); - dev->hard_start_xmit = &cops_send_packet; + dev->hard_start_xmit = cops_send_packet; + dev->tx_timeout = cops_timeout; + dev->watchdog_timeo = HZ * 2; dev->hard_header = cops_hard_header; dev->get_stats = cops_get_stats; dev->open = cops_open; dev->stop = cops_close; - dev->do_ioctl = &cops_ioctl; - dev->set_multicast_list = &set_multicast_list; + dev->do_ioctl = cops_ioctl; + dev->set_multicast_list = set_multicast_list; dev->mc_list = NULL; /* Tell the user where the card is and what mode we're in. */ @@ -424,10 +426,7 @@ static int cops_open(struct net_device *dev) cops_jumpstart(dev); /* Start the card up. */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - + netif_start_queue(dev); #ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -501,8 +500,7 @@ static void cops_reset(struct net_device *dev, int sleep) else udelay(333333); } - dev->tbusy=0; - + netif_wake_queue(dev); return; } @@ -673,6 +671,7 @@ static int cops_nodeid (struct net_device *dev, int nodeid) /* * Poll the Tangent type cards to see if we have work. */ + static void cops_poll(unsigned long ltdev) { int ioaddr, status; @@ -691,7 +690,7 @@ static void cops_poll(unsigned long ltdev) if(status & TANG_RX_READY) cops_rx(dev); if(status & TANG_TX_READY) - dev->tbusy = 0; + netif_wake_queue(dev); status = inb(ioaddr+TANG_CARD_STATUS); } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); @@ -712,14 +711,6 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) int ioaddr, status; int boguscount = 0; - if(dev == NULL) - { - printk(KERN_WARNING "%s: irq %d for unknown device.\n", - cardname, irq); - return; - } - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct cops_local *)dev->priv; @@ -730,8 +721,7 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) status=inb(ioaddr+DAYNA_CARD_STATUS); if((status&0x03)==DAYNA_RX_REQUEST) cops_rx(dev); - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } while(++boguscount < 20); } else @@ -741,13 +731,11 @@ static void cops_interrupt(int irq, void *dev_id, struct pt_regs * regs) if(status & TANG_RX_READY) cops_rx(dev); if(status & TANG_TX_READY) - dev->tbusy = 0; + netif_wake_queue(dev); status=inb(ioaddr+TANG_CARD_STATUS); - } while((++boguscount < 20) && - (status&(TANG_RX_READY|TANG_TX_READY))); + } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); } - dev->interrupt = 0; return; } @@ -762,7 +750,10 @@ static void cops_rx(struct net_device *dev) struct cops_local *lp = (struct cops_local *)dev->priv; int ioaddr = dev->base_addr; int boguscount = 0; + unsigned long flags; + + save_flags(flags); cli(); /* Disable interrupts. */ if(lp->board==DAYNA) @@ -798,7 +789,7 @@ static void cops_rx(struct net_device *dev) skb = dev_alloc_skb(pkt_len); if(skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", + printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++; while(pkt_len--) /* Discard packet */ @@ -814,12 +805,12 @@ static void cops_rx(struct net_device *dev) if(lp->board==DAYNA) outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */ - sti(); /* Restore interrupts. */ + restore_flags(flags); /* Restore interrupts. */ /* Check for bad response length */ if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) { - printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", + printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", dev->name, pkt_len); lp->stats.tx_errors++; kfree_skb(skb); @@ -837,7 +828,7 @@ static void cops_rx(struct net_device *dev) /* One last check to make sure we have a good packet. */ if(rsp_type != LAP_RESPONSE) { - printk("%s: Bad packet type %d.\n", dev->name, rsp_type); + printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type); lp->stats.tx_errors++; kfree_skb(skb); return; @@ -857,79 +848,72 @@ static void cops_rx(struct net_device *dev) return; } +static void cops_timeout(struct net_device *dev) +{ + struct cops_local *lp = (struct cops_local *)dev->priv; + int ioaddr = dev->base_addr; + + lp->stats.tx_errors++; + if(lp->board==TANGENT) + { + if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) + printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); + } + printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); + cops_jumpstart(dev); /* Restart the card. */ + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + + /* * Make the card transmit a LocalTalk packet. */ + static int cops_send_packet(struct sk_buff *skb, struct net_device *dev) { struct cops_local *lp = (struct cops_local *)dev->priv; int ioaddr = dev->base_addr; - - if(dev->tbusy) - { - /* - * If we get here, some higher level has decided we are broken. - * There should really be a "kick me" function call instead. - */ - int tickssofar = jiffies - dev->trans_start; - if(tickssofar < 5) - return 1; - lp->stats.tx_errors++; - if(lp->board==TANGENT) - { - if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) - printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); - } - printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); - cops_jumpstart(dev); /* Restart the card. */ - dev->tbusy=0; - dev->trans_start = jiffies; - } + unsigned long flags; /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. + * Block a timer-based transmit from overlapping. */ - if(test_and_set_bit(0, (void*) &dev->tbusy) != 0) - printk(KERN_WARNING "%s: Transmitter access conflict.\n", - dev->name); - else - { - cli(); /* Disable interrupts. */ - if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ - while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); - if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ - while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0); - - /* Output IO length. */ - outb(skb->len, ioaddr); - if(lp->board == DAYNA) - outb(skb->len >> 8, ioaddr); - else - outb((skb->len >> 8)&0x0FF, ioaddr); - - /* Output IO code. */ - outb(LAP_WRITE, ioaddr); + + netif_stop_queue(dev); + + save_flags(flags); + cli(); /* Disable interrupts. */ + if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ + while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0); + + /* Output IO length. */ + outb(skb->len, ioaddr); + if(lp->board == DAYNA) + outb(skb->len >> 8, ioaddr); + else + outb((skb->len >> 8)&0x0FF, ioaddr); - if(lp->board == DAYNA) /* Check the transmit buffer again. */ - while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); + /* Output IO code. */ + outb(LAP_WRITE, ioaddr); - outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ + if(lp->board == DAYNA) /* Check the transmit buffer again. */ + while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); - if(lp->board==DAYNA) /* Dayna requires you kick the card */ - outb(1, ioaddr+DAYNA_INT_CARD); + outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ - sti(); /* Restore interrupts. */ + if(lp->board==DAYNA) /* Dayna requires you kick the card */ + outb(1, ioaddr+DAYNA_INT_CARD); - /* Done sending packet, update counters and cleanup. */ - lp->stats.tx_packets++; - lp->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - } + restore_flags(flags); /* Restore interrupts. */ + /* Done sending packet, update counters and cleanup. */ + lp->stats.tx_packets++; + lp->stats.tx_bytes += skb->len; + dev->trans_start = jiffies; dev_kfree_skb (skb); - dev->tbusy = 0; - return 0; } @@ -1005,9 +989,7 @@ static int cops_close(struct net_device *dev) if(lp->board==TANGENT && dev->irq==0) del_timer(&cops_timer); - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); #ifdef MODULE MOD_DEC_USE_COUNT; #endif @@ -1019,7 +1001,7 @@ static int cops_close(struct net_device *dev) * Get the current statistics. * This may be called with the card open or closed. */ -static struct enet_statistics *cops_get_stats(struct net_device *dev) +static struct net_device_stats *cops_get_stats(struct net_device *dev) { struct cops_local *lp = (struct cops_local *)dev->priv; return &lp->stats; diff --git a/drivers/net/de600.c b/drivers/net/de600.c index 1805ae5f32c1..0b581d7e52b4 100644 --- a/drivers/net/de600.c +++ b/drivers/net/de600.c @@ -348,7 +348,6 @@ de600_open(struct net_device *dev) } MOD_INC_USE_COUNT; - dev->start = 1; if (adapter_init(dev)) { return 1; } @@ -369,9 +368,8 @@ de600_close(struct net_device *dev) de600_put_command(0); select_prn(); - if (dev->start) { + if (test_bit(LINK_STATE_START, &dev->state)) { /* perhaps not needed? */ free_irq(DE600_IRQ, dev); - dev->start = 0; MOD_DEC_USE_COUNT; } return 0; @@ -400,6 +398,7 @@ trigger_interrupt(struct net_device *dev) static int de600_start_xmit(struct sk_buff *skb, struct net_device *dev) { + unsigned long flags; int transmit_from; int len; int tickssofar; @@ -429,6 +428,7 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev) if ((len = skb->len) < RUNT) len = RUNT; + save_flags(flags); cli(); select_nic(); tx_fifo[tx_fifo_in] = transmit_from = tx_page_adr(tx_fifo_in) - len; @@ -440,7 +440,7 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev) de600_read_byte(READ_DATA, dev); if (was_down || (de600_read_byte(READ_DATA, dev) != 0xde)) { if (adapter_init(dev)) { - sti(); + restore_flags(flags); return 1; } } @@ -452,17 +452,20 @@ de600_start_xmit(struct sk_buff *skb, struct net_device *dev) if (free_tx_pages-- == TX_PAGES) { /* No transmission going on */ dev->trans_start = jiffies; - dev->tbusy = 0; /* allow more packets into adapter */ + netif_start_queue(dev); /* allow more packets into adapter */ /* Send page and generate a faked interrupt */ de600_setup_address(transmit_from, TX_ADDR); de600_put_command(TX_ENABLE); } else { - dev->tbusy = !free_tx_pages; + if (free_tx_pages) + netif_start_queue(dev); + else + netif_stop_queue(dev); select_prn(); } - sti(); /* interrupts back on */ + restore_flags(flags); #ifdef FAKE_SMALL_MAX /* This will "patch" the socket TCP proto at an early moment */ @@ -489,12 +492,11 @@ de600_interrupt(int irq, void *dev_id, struct pt_regs * regs) int boguscount = 0; /* This might just as well be deleted now, no crummy drivers present :-) */ - if ((dev == NULL) || (dev->start == 0) || (DE600_IRQ != irq)) { + if ((dev == NULL) || (DE600_IRQ != irq)) { printk("%s: bogus interrupt %d\n", dev?dev->name:"DE-600", irq); return; } - dev->interrupt = 1; select_nic(); irq_status = de600_read_status(dev); @@ -521,13 +523,11 @@ de600_interrupt(int irq, void *dev_id, struct pt_regs * regs) */ /* Enable adapter interrupts */ - dev->interrupt = 0; select_prn(); if (retrig) trigger_interrupt(dev); - sti(); return; } @@ -538,7 +538,6 @@ de600_tx_intr(struct net_device *dev, int irq_status) * Returns 1 if tx still not done */ - mark_bh(NET_BH); /* Check if current transmission is done yet */ if (irq_status & TX_BUSY) return 1; /* tx not done, try again */ @@ -549,7 +548,7 @@ de600_tx_intr(struct net_device *dev, int irq_status) tx_fifo_out = (tx_fifo_out + 1) % TX_PAGES; ++free_tx_pages; ((struct net_device_stats *)(dev->priv))->tx_packets++; - dev->tbusy = 0; + netif_wake_queue(dev); } /* More to send, or resend last packet? */ @@ -571,12 +570,15 @@ static void de600_rx_intr(struct net_device *dev) { struct sk_buff *skb; + unsigned long flags; int i; int read_from; int size; register unsigned char *buffer; + save_flags(flags); cli(); + /* Get size of received packet */ size = de600_read_byte(RX_LEN, dev); /* low byte */ size += (de600_read_byte(RX_LEN, dev) << 8); /* high byte */ @@ -586,7 +588,8 @@ de600_rx_intr(struct net_device *dev) read_from = rx_page_adr(); next_rx_page(); de600_put_command(RX_ENABLE); - sti(); + + restore_flags(flags); if ((size < 32) || (size > 1535)) { printk("%s: Bogus packet size %d.\n", dev->name, size); @@ -596,7 +599,7 @@ de600_rx_intr(struct net_device *dev) } skb = dev_alloc_skb(size+2); - sti(); + restore_flags(flags); if (skb == NULL) { printk("%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, size); @@ -738,7 +741,7 @@ adapter_init(struct net_device *dev) de600_close(dev); #endif /* SHUTDOWN_WHEN_LOST */ was_down = 1; - dev->tbusy = 1; /* Transmit busy... */ + netif_stop_queue(dev); /* Transmit busy... */ restore_flags(flags); return 1; /* failed */ } @@ -748,8 +751,7 @@ adapter_init(struct net_device *dev) was_down = 0; } - dev->tbusy = 0; /* Transmit busy... */ - dev->interrupt = 0; + netif_start_queue(dev); tx_fifo_in = 0; tx_fifo_out = 0; free_tx_pages = TX_PAGES; diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c index 10366f2f8aca..af2db03bcf1c 100644 --- a/drivers/net/fmv18x.c +++ b/drivers/net/fmv18x.c @@ -112,9 +112,10 @@ extern int fmv18x_probe(struct net_device *dev); static int fmv18x_probe1(struct net_device *dev, short ioaddr); static int net_open(struct net_device *dev); -static int net_send_packet(struct sk_buff *skb, struct net_device *dev); +static int net_send_packet(struct sk_buff *skb, struct net_device *dev); static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void net_rx(struct net_device *dev); +static void net_timeout(struct net_device *dev); static int net_close(struct net_device *dev); static struct net_device_stats *net_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); @@ -276,9 +277,11 @@ int __init fmv18x_probe1(struct net_device *dev, short ioaddr) dev->open = net_open; dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - dev->set_multicast_list = &set_multicast_list; + dev->hard_start_xmit = net_send_packet; + dev->tx_timeout = net_timeout; + dev->watchdog_timeo = HZ/10; + dev->get_stats = net_get_stats; + dev->set_multicast_list = set_multicast_list; /* Fill in the fields of 'dev' with ethernet-generic values. */ @@ -310,10 +313,8 @@ static int net_open(struct net_device *dev) outb(0xff, ioaddr + RX_STATUS); lp->open_time = jiffies; - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - + netif_start_queue(dev); + /* Enable the IRQ of the LAN Card */ outb(0x80, ioaddr + FJ_CONFIG1); @@ -325,93 +326,86 @@ static int net_open(struct net_device *dev) return 0; } -static int -net_send_packet(struct sk_buff *skb, struct net_device *dev) +static void net_timeout(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; + unsigned long flags; + + + printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name, + htons(inw(ioaddr + TX_STATUS)), + inb(ioaddr + TX_STATUS) & 0x80 + ? "IRQ conflict" : "network cable problem"); + printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", + dev->name, htons(inw(ioaddr + 0)), + htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), + htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), + htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), + htons(inw(ioaddr +14))); + printk(KERN_WARNING "eth card: %04x %04x\n", + htons(inw(ioaddr+FJ_STATUS0)), + htons(inw(ioaddr+FJ_CONFIG0))); + lp->stats.tx_errors++; + /* ToDo: We should try to restart the adaptor... */ + save_flags(flags); + cli(); - if (dev->tbusy) { - /* If we get here, some higher level has decided we are broken. - There should really be a "kick me" function call instead. */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 10) - return 1; - printk("%s: transmit timed out with status %04x, %s?\n", dev->name, - htons(inw(ioaddr + TX_STATUS)), - inb(ioaddr + TX_STATUS) & 0x80 - ? "IRQ conflict" : "network cable problem"); - printk("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", - dev->name, htons(inw(ioaddr + 0)), - htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)), - htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)), - htons(inw(ioaddr +10)), htons(inw(ioaddr +12)), - htons(inw(ioaddr +14))); - printk("eth card: %04x %04x\n", - htons(inw(ioaddr+FJ_STATUS0)), - htons(inw(ioaddr+FJ_CONFIG0))); - lp->stats.tx_errors++; - /* ToDo: We should try to restart the adaptor... */ - cli(); - - /* Initialize LAN Controller and LAN Card */ - outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ - outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ - outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ - outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ - net_open(dev); - - sti(); - } - - /* Block a timer-based transmit from overlapping. This could better be - done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - printk("%s: Transmitter access conflict.\n", dev->name); - else { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - if (length > ETH_FRAME_LEN) { - if (net_debug) - printk("%s: Attempting to send a large packet (%d bytes).\n", - dev->name, length); - return 1; - } + /* Initialize LAN Controller and LAN Card */ + outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */ + outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */ + outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */ + outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */ + net_open(dev); + restore_flags(flags); +} - if (net_debug > 4) - printk("%s: Transmitting a packet of length %lu.\n", dev->name, - (unsigned long)skb->len); - - /* We may not start transmitting unless we finish transferring - a packet into the Tx queue. During executing the following - codes we possibly catch a Tx interrupt. Thus we flag off - tx_queue_ready, so that we prevent the interrupt routine - (net_interrupt) to start transmitting. */ - lp->tx_queue_ready = 0; - { - outw(length, ioaddr + DATAPORT); - outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - - lp->tx_queue++; - lp->tx_queue_len += length + 2; - } - lp->tx_queue_ready = 1; - - if (lp->tx_started == 0) { - /* If the Tx is idle, always trigger a transmit. */ - outb(0x80 | lp->tx_queue, ioaddr + TX_START); - lp->tx_queue = 0; - lp->tx_queue_len = 0; - dev->trans_start = jiffies; - lp->tx_started = 1; - dev->tbusy = 0; - } else if (lp->tx_queue_len < 4096 - 1502) - /* Yes, there is room for one more packet. */ - dev->tbusy = 0; +static int net_send_packet(struct sk_buff *skb, struct net_device *dev) +{ + struct net_local *lp = (struct net_local *)dev->priv; + int ioaddr = dev->base_addr; + short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + unsigned char *buf = skb->data; + + /* Block a transmit from overlapping. */ + + netif_stop_queue(dev); + + if (length > ETH_FRAME_LEN) { + if (net_debug) + printk("%s: Attempting to send a large packet (%d bytes).\n", + dev->name, length); + return 1; } - dev_kfree_skb (skb); - + if (net_debug > 4) + printk("%s: Transmitting a packet of length %lu.\n", dev->name, + (unsigned long)skb->len); + /* We may not start transmitting unless we finish transferring + a packet into the Tx queue. During executing the following + codes we possibly catch a Tx interrupt. Thus we flag off + tx_queue_ready, so that we prevent the interrupt routine + (net_interrupt) to start transmitting. */ + lp->tx_queue_ready = 0; + { + outw(length, ioaddr + DATAPORT); + outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); + lp->tx_queue++; + lp->tx_queue_len += length + 2; + } + lp->tx_queue_ready = 1; + if (lp->tx_started == 0) { + /* If the Tx is idle, always trigger a transmit. */ + outb(0x80 | lp->tx_queue, ioaddr + TX_START); + lp->tx_queue = 0; + lp->tx_queue_len = 0; + dev->trans_start = jiffies; + lp->tx_started = 1; + netif_wake_queue(dev); + } else if (lp->tx_queue_len < 4096 - 1502) + /* Yes, there is room for one more packet. */ + netif_wake_queue(dev); + + dev_kfree_skb(skb); return 0; } @@ -424,12 +418,6 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs) struct net_local *lp; int ioaddr, status; - if (dev == NULL) { - printk ("fmv18x_interrupt(): irq %d for unknown device.\n", irq); - return; - } - dev->interrupt = 1; - ioaddr = dev->base_addr; lp = (struct net_local *)dev->priv; status = inw(ioaddr + TX_STATUS); @@ -467,23 +455,18 @@ net_interrupt(int irq, void *dev_id, struct pt_regs *regs) lp->tx_queue = 0; lp->tx_queue_len = 0; dev->trans_start = jiffies; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue(dev); /* Inform upper layers. */ } else { lp->tx_started = 0; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue(dev); /* Inform upper layers. */ } } } - - dev->interrupt = 0; return; } /* We have a good packet(s), get it/them out of the buffers. */ -static void -net_rx(struct net_device *dev) +static void net_rx(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; int ioaddr = dev->base_addr; @@ -578,9 +561,8 @@ static int net_close(struct net_device *dev) ((struct net_local *)dev->priv)->open_time = 0; - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); + /* Set configuration register 0 to disable Tx and Rx. */ outb(0xda, ioaddr + CONFIG_0); diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c index 9a81ff0f73fc..8e5bca56a3ff 100644 --- a/drivers/net/ni5010.c +++ b/drivers/net/ni5010.c @@ -106,6 +106,7 @@ static int ni5010_open(struct net_device *dev); static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev); static void ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void ni5010_rx(struct net_device *dev); +static void ni5010_timeout(struct net_device *dev); static int ni5010_close(struct net_device *dev); static struct net_device_stats *ni5010_get_stats(struct net_device *dev); static void ni5010_set_multicast_list(struct net_device *dev); @@ -320,15 +321,13 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr) dev->stop = ni5010_close; dev->hard_start_xmit = ni5010_send_packet; dev->get_stats = ni5010_get_stats; - dev->set_multicast_list = &ni5010_set_multicast_list; + dev->set_multicast_list = ni5010_set_multicast_list; + dev->tx_timeout = ni5010_timeout; + dev->watchdog_timeo = HZ/20; /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ /* Shut up the ni5010 */ @@ -403,10 +402,8 @@ static int ni5010_open(struct net_device *dev) outb(0, EDLC_RESET); /* Un-reset the ni5010 */ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; - + netif_start_queue(dev); + if (NI5010_DEBUG) show_registers(dev); MOD_INC_USE_COUNT; @@ -426,42 +423,31 @@ static void reset_receiver(struct net_device *dev) outb(0xff, EDLC_RMASK); /* Enable all rcv interrupts */ } +static void ni5010_timeout(struct net_device *dev) +{ + printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, + tx_done(dev) ? "IRQ conflict" : "network cable problem"); + /* Try to restart the adaptor. */ + /* FIXME: Give it a real kick here */ + chipset_init(dev, 1); + dev->trans_start = jiffies; + netif_wake_queue(dev); +} + static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev) { + int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + PRINTK2((KERN_DEBUG "%s: entering ni5010_send_packet\n", dev->name)); - if (dev->tbusy) { - /* - * If we get here, some higher level has decided we are broken. - * There should really be a "kick me" function call instead. - */ - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - printk("tbusy\n"); - printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name, - tx_done(dev) ? "IRQ conflict" : "network cable problem"); - /* Try to restart the adaptor. */ - /* FIXME: Give it a real kick here */ - chipset_init(dev, 1); - dev->tbusy=0; - dev->trans_start = jiffies; - } /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but test_and_set_bit() works as well. + * Block sending */ - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name); - return 1; - } else { - int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - - hardware_send_packet(dev, (unsigned char *)skb->data, length); - dev->trans_start = jiffies; - } + + netif_stop_queue(dev); + hardware_send_packet(dev, (unsigned char *)skb->data, length); + dev->trans_start = jiffies; dev_kfree_skb (skb); - return 0; } @@ -469,23 +455,13 @@ static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev) * The typical workload of the driver: * Handle the network interface interrupts. */ -static void -ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static void ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; struct ni5010_local *lp; int ioaddr, status; int xmit_was_error = 0; - if (dev == NULL || dev->irq != irq) { - printk(KERN_WARNING "%s: irq %d for unknown device.\n", - boardname, irq); - return; - } - - if (dev->interrupt) printk(KERN_WARNING "%s: Reentering IRQ-handler!\n", dev->name); - dev->interrupt = 1; - PRINTK2((KERN_DEBUG "%s: entering ni5010_interrupt\n", dev->name)); ioaddr = dev->base_addr; @@ -507,8 +483,6 @@ ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!xmit_was_error) reset_receiver(dev); - - dev->interrupt = 0; return; } @@ -530,8 +504,7 @@ static void dump_packet(void *buf, int len) } /* We have a good packet, get it out of the buffer. */ -static void -ni5010_rx(struct net_device *dev) +static void ni5010_rx(struct net_device *dev) { struct ni5010_local *lp = (struct ni5010_local *)dev->priv; int ioaddr = dev->base_addr; @@ -624,8 +597,7 @@ static int process_xmt_interrupt(struct net_device *dev) lp->stats.tx_packets++; lp->stats.tx_bytes += lp->o_pkt_size; - dev->tbusy = 0; - mark_bh(NET_BH); /* Inform upper layers. */ + netif_wake_queue(dev); PRINTK2((KERN_DEBUG "%s: sent packet, size=%#4.4x\n", dev->name, lp->o_pkt_size)); @@ -634,8 +606,7 @@ static int process_xmt_interrupt(struct net_device *dev) } /* The inverse routine to ni5010_open(). */ -static int -ni5010_close(struct net_device *dev) +static int ni5010_close(struct net_device *dev) { int ioaddr = dev->base_addr; @@ -647,9 +618,8 @@ ni5010_close(struct net_device *dev) outb(0, IE_MMODE); outb(RS_RESET, EDLC_RESET); - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); + MOD_DEC_USE_COUNT; PRINTK((KERN_DEBUG "%s: %s closed down\n", dev->name, boardname)); return 0; @@ -658,8 +628,7 @@ ni5010_close(struct net_device *dev) /* Get the current statistics. This may be called with the card open or closed. */ -static struct net_device_stats * -ni5010_get_stats(struct net_device *dev) +static struct net_device_stats *ni5010_get_stats(struct net_device *dev) { struct ni5010_local *lp = (struct ni5010_local *)dev->priv; @@ -681,8 +650,7 @@ ni5010_get_stats(struct net_device *dev) num_addrs > 0 Multicast mode, receive normal and MC packets, and do best-effort filtering. */ -static void -ni5010_set_multicast_list(struct net_device *dev) +static void ni5010_set_multicast_list(struct net_device *dev) { short ioaddr = dev->base_addr; @@ -748,6 +716,8 @@ extern void hardware_send_packet(struct net_device *dev, char *buf, int length) restore_flags(flags); + netif_wake_queue(dev); + if (NI5010_DEBUG) show_registers(dev); } diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c index 7efc0dca6301..de4356a2fa5f 100644 --- a/drivers/net/ni52.c +++ b/drivers/net/ni52.c @@ -199,6 +199,7 @@ static int ni52_close(struct net_device *dev); static int ni52_send_packet(struct sk_buff *,struct net_device *); static struct net_device_stats *ni52_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); +static void ni52_timeout(struct net_device *dev); #if 0 static void ni52_dump(struct net_device *,void *); #endif @@ -244,9 +245,7 @@ static int ni52_close(struct net_device *dev) ni_reset586(); /* the hard way to stop the receiver */ - dev->start = 0; - dev->tbusy = 0; - + netif_stop_queue(dev); MOD_DEC_USE_COUNT; return 0; @@ -269,10 +268,7 @@ static int ni52_open(struct net_device *dev) return -EAGAIN; } - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; - + netif_start_queue(dev); MOD_INC_USE_COUNT; return 0; /* most done by init */ @@ -512,20 +508,18 @@ static int __init ni52_probe1(struct net_device *dev,int ioaddr) printk("IRQ %d (assigned and not checked!).\n",dev->irq); } - dev->open = &ni52_open; - dev->stop = &ni52_close; - dev->get_stats = &ni52_get_stats; - dev->hard_start_xmit = &ni52_send_packet; - dev->set_multicast_list = &set_multicast_list; + dev->open = ni52_open; + dev->stop = ni52_close; + dev->get_stats = ni52_get_stats; + dev->tx_timeout = ni52_timeout; + dev->watchdog_timeo = HZ/20; + dev->hard_start_xmit = ni52_send_packet; + dev->set_multicast_list = set_multicast_list; dev->if_port = 0; ether_setup(dev); - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 0; - return 0; } @@ -831,8 +825,6 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr) if(debuglevel > 1) printk("I"); - dev->interrupt = 1; - WAIT_4_SCB_CMD(); /* wait for last command */ while((stat=p->scb->cus & STAT_MASK)) @@ -866,7 +858,7 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr) #ifndef NO_NOPCOMMANDS if(stat & STAT_CNA) /* CU went 'not ready' */ { - if(dev->start) + if(test_bit(LINK_STATE_START, &dev->state)) printk("%s: oops! CU has left active state. stat: %04x/%02x.\n",dev->name,(int) stat,(int) p->scb->cus); } #endif @@ -885,8 +877,6 @@ static void ni52_interrupt(int irq,void *dev_id,struct pt_regs *reg_ptr) if(debuglevel > 1) printk("i"); - - dev->interrupt = 0; } /******************************************************* @@ -1083,9 +1073,7 @@ static void ni52_xmt_int(struct net_device *dev) if( (++p->xmit_last) == NUM_XMIT_BUFFS) p->xmit_last = 0; #endif - - dev->tbusy = 0; - mark_bh(NET_BH); + netif_wake_queue(dev); } /*********************************************************** @@ -1104,6 +1092,40 @@ static void startrecv586(struct net_device *dev) WAIT_4_SCB_CMD_RUC(); /* wait for accept cmd. (no timeout!!) */ } +static void ni52_timeout(struct net_device *dev) +{ + struct priv *p = (struct priv *) dev->priv; +#ifndef NO_NOPCOMMANDS + if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */ + { + netif_wake_queue(dev); +#ifdef DEBUG + printk("%s: strange ... timeout with CU active?!?\n",dev->name); + printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); +#endif + p->scb->cmd_cuc = CUC_ABORT; + ni_attn586(); + WAIT_4_SCB_CMD(); + p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); + p->scb->cmd_cuc = CUC_START; + ni_attn586(); + WAIT_4_SCB_CMD(); + dev->trans_start = jiffies; + return 0; + } +#endif + { +#ifdef DEBUG + printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus); + printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); + printk("%s: check, whether you set the right interrupt number!\n",dev->name); +#endif + ni52_close(dev); + ni52_open(dev); + } + dev->trans_start = jiffies; +} + /****************************************************** * send frame */ @@ -1116,62 +1138,21 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev) #endif struct priv *p = (struct priv *) dev->priv; - if(dev->tbusy) - { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < 5) - return 1; - -#ifndef NO_NOPCOMMANDS - if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */ - { - dev->tbusy = 0; -#ifdef DEBUG - printk("%s: strange ... timeout with CU active?!?\n",dev->name); - printk("%s: X0: %04x N0: %04x N1: %04x %d\n",dev->name,(int)p->xmit_cmds[0]->cmd_status,(int)p->nop_cmds[0]->cmd_status,(int)p->nop_cmds[1]->cmd_status,(int)p->nop_point); -#endif - p->scb->cmd_cuc = CUC_ABORT; - ni_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd_cuc = CUC_START; - ni_attn586(); - WAIT_4_SCB_CMD(); - dev->trans_start = jiffies; - return 0; - } - else -#endif - { -#ifdef DEBUG - printk("%s: xmitter timed out, try to restart! stat: %02x\n",dev->name,p->scb->cus); - printk("%s: command-stats: %04x %04x\n",dev->name,p->xmit_cmds[0]->cmd_status,p->xmit_cmds[1]->cmd_status); - printk("%s: check, whether you set the right interrupt number!\n",dev->name); -#endif - ni52_close(dev); - ni52_open(dev); - } - dev->trans_start = jiffies; - return 0; - } - if(skb->len > XMIT_BUFF_SIZE) { printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len); return 0; } - if (test_and_set_bit(0, (void*)&dev->tbusy)) { - printk("%s: Transmitter access conflict.\n", dev->name); - return 1; - } + netif_stop_queue(dev); + #if(NUM_XMIT_BUFFS > 1) - else if(test_and_set_bit(0,(void *) &p->lock)) { + if(test_and_set_bit(0,(void *) &p->lock)) { printk("%s: Queue was locked\n",dev->name); return 1; } -#endif else +#endif { memcpy((char *)p->xmit_cbuffs[p->xmit_count],(char *)(skb->data),skb->len); len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; @@ -1231,7 +1212,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev) next_nop = 0; p->xmit_cmds[p->xmit_count]->cmd_status = 0; - /* linkpointer of xmit-command already points to next nop cmd */ + /* linkpointer of xmit-command already points to next nop cmd */ p->nop_cmds[next_nop]->cmd_link = make16((p->nop_cmds[next_nop])); p->nop_cmds[next_nop]->cmd_status = 0; @@ -1240,11 +1221,11 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev) p->xmit_count = next_nop; { - long flags; + unsigned long flags; save_flags(flags); cli(); if(p->xmit_count != p->xmit_last) - dev->tbusy = 0; + netif_wake_queue(dev); p->lock = 0; restore_flags(flags); } @@ -1283,23 +1264,16 @@ static struct net_device_stats *ni52_get_stats(struct net_device *dev) /******************************************************** * Set MC list .. */ + static void set_multicast_list(struct net_device *dev) { - if(!dev->start) - { - printk("%s: Can't apply promiscuous/multicastmode to a not running interface.\n",dev->name); - return; - } - - dev->start = 0; - + netif_stop_queue(dev); ni_disint(); alloc586(dev); init586(dev); startrecv586(dev); ni_enaint(); - - dev->start = 1; + netif_wake_queue(dev); } #ifdef MODULE -- 2.39.5