]> git.neil.brown.name Git - history.git/commitdiff
Import 2.3.45 2.3.45
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:26 +0000 (15:31 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:31:26 +0000 (15:31 -0500)
62 files changed:
CREDITS
arch/i386/defconfig
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
drivers/block/cs5530.c
drivers/net/3c505.c
drivers/net/3c505.h
drivers/net/Config.in
drivers/net/atp.c
drivers/net/atp.h
drivers/net/defxx.c
drivers/net/eepro100.c
drivers/net/epic100.c
drivers/net/eth16i.c
drivers/net/ewrk3.c
drivers/net/fc/iph5526.c
drivers/net/fmv18x.c
drivers/net/hamradio/bpqether.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/scc.c
drivers/net/hamradio/yam.c
drivers/net/ni65.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/tulip_cb.c
drivers/net/rtl8129.c
drivers/net/sis900.c
drivers/net/sk_g16.c
drivers/net/tulip.c
drivers/net/wan/cycx_x25.c
drivers/net/wan/sdla_chdlc.c
drivers/net/wan/sdla_fr.c
drivers/net/wan/sdla_ppp.c
drivers/net/wan/sdla_x25.c
drivers/scsi/eata.c
drivers/scsi/hosts.h
drivers/sound/ac97_codec.c
drivers/sound/ac97_codec.h
fs/Config.in
fs/adfs/inode.c
fs/affs/inode.c
fs/attr.c
fs/fat/cache.c
fs/inode.c
fs/locks.c
fs/ncpfs/inode.c
fs/nfs/inode.c
fs/smbfs/inode.c
fs/umsdos/inode.c
fs/umsdos/namei.c
include/linux/fs.h
include/linux/mm.h
kernel/fork.c
mm/filemap.c
mm/memory.c
mm/mmap.c
net/irda/irda_device.c
net/irda/irlan/irlan_client.c
net/irda/irlan/irlan_common.c
net/irda/irlan/irlan_eth.c
net/netrom/nr_dev.c
net/rose/rose_dev.c
net/wanrouter/wanmain.c

diff --git a/CREDITS b/CREDITS
index ad3f5c3ffb077636f2b0b24d39b348335bef506d..7db905aebfc830f65a01cc8860d3e69185166482 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -637,13 +637,6 @@ S: Grevgatan 11
 S: S-114 53 Stockholm
 S: Sweden
 
-N: Stephane Eranian
-E: eranian@hpl.hp.com
-D: Linux/ia64
-S: 1501 Page Mill Rd, MS 1U17
-S: Palo Alto, CA 94304
-S: USA
-
 N: Paal-Kristian Engstad
 E: engstad@intermetrics.com
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
@@ -651,6 +644,13 @@ S: 17101 Springdale Street #225
 S: Huntington Beach, California 92649
 S: USA
 
+N: Stephane Eranian
+E: eranian@hpl.hp.com
+D: Linux/ia64
+S: 1501 Page Mill Rd, MS 1U17
+S: Palo Alto, CA 94304
+S: USA
+
 N: Johannes Erdfelt
 E: jerdfelt@valinux.com
 D: Linux/IA-64 bootloader and kernel goop, USB
@@ -1832,17 +1832,17 @@ S: M"ullerstr. 69
 S: 13349 Berlin
 S: Germany
 
-N: Nicolas Pitre
-E: nico@cam.org
-D: StrongARM SA1100 support integrator & hacker
-S: Montreal, Quebec, Canada
-
 N: Emanuel Pirker
 E: epirker@edu.uni-klu.ac.at
 D: AIC5800 IEEE 1394, RAW I/O on 1394
 D: Starter of Linux1394 effort
 S: ask per mail for current address
 
+N: Nicolas Pitre
+E: nico@cam.org
+D: StrongARM SA1100 support integrator & hacker
+S: Montreal, Quebec, Canada
+
 N: Ken Pizzini
 E: ken@halcyon.com
 D: CDROM driver "sonycd535" (Sony CDU-535/531)
@@ -2621,13 +2621,6 @@ D: CMI8330 support is sb_card.c
 D: ISAPnP fixes in sb_card.c
 S: Italy
 
-N: Alessandro Zummo
-E: azummo@ita.flashnet.it
-W: http://freepage.logicom.it/azummo/
-D: CMI8330 support is sb_card.c
-D: ISAPnP fixes in sb_card.c
-S: Italy
-
 N: Marc Zyngier
 E: maz@wild-wind.fr.eu.org
 D: MD driver
index fcd22384ffb5537482c58da3ad0ee087ac3f39b8..0f3a762a3993a587c1f618de12fbe7086d21ee78 100644 (file)
@@ -273,7 +273,6 @@ CONFIG_NET_ETHERNET=y
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_APRICOT is not set
-# CONFIG_CS89x0 is not set
 # CONFIG_DE4X5 is not set
 # CONFIG_TULIP is not set
 # CONFIG_DGRS is not set
index d46b45378101a7050985635bd2cd14c73729958f..890ed9d068ac12ce37f4a3b41890e44f41f3803a 100644 (file)
@@ -1366,7 +1366,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
        if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) {
                struct vm_area_struct *vmaring;
                struct file *file;
-               struct inode *inode;
+               struct address_space *mapping;
                unsigned long flags, offset, vaddr, start;
                int alias_found = 0;
                pgd_t *pgdp;
@@ -1378,10 +1378,10 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
                file = vma->vm_file;
                if (!file)
                        goto done;
-               inode = file->f_dentry->d_inode;
+               mapping = file->f_dentry->d_inode->i_mapping;
                offset = (address & PAGE_MASK) - vma->vm_start;
-               spin_lock(&inode->i_shared_lock);
-               vmaring = inode->i_mmap; 
+               spin_lock(&mapping->i_shared_lock);
+               vmaring = mapping->i_mmap; 
                do {
                        /* Do not mistake ourselves as another mapping. */
                        if(vmaring == vma)
@@ -1414,7 +1414,7 @@ static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma,
                                }
                        }
                } while ((vmaring = vmaring->vm_next_share) != NULL);
-               spin_unlock(&inode->i_shared_lock);
+               spin_unlock(&mapping->i_shared_lock);
 
                if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) {
                        pgdp = srmmu_pgd_offset(vma->vm_mm, address);
index ae5d5e3714cc619c737c06ed881026ec314ec24d..5df4febd4432e2997b6d47d5fcb05fdc37cbaf1b 100644 (file)
@@ -2418,11 +2418,12 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
        if(dentry)
                inode = dentry->d_inode;
        if(inode) {
+               struct address_space *mapping = inode->i_mapping;
                unsigned long offset = (address & PAGE_MASK) - vma->vm_start;
                struct vm_area_struct *vmaring;
                int alias_found = 0;
-               spin_lock(&inode->i_shared_lock);
-               vmaring = inode->i_mmap; 
+               spin_lock(&mapping->i_shared_lock);
+               vmaring = mapping->i_mmap; 
                do {
                        unsigned long vaddr = vmaring->vm_start + offset;
                        unsigned long start;
@@ -2453,7 +2454,7 @@ static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long addr
                                }
                        }
                } while ((vmaring = vmaring->vm_next_share) != NULL);
-               spin_unlock(&inode->i_shared_lock);
+               spin_unlock(&mapping->i_shared_lock);
 
                if (alias_found && !(pte_val(pte) & _SUN4C_PAGE_NOCACHE)) {
                        pgdp = sun4c_pgd_offset(vma->vm_mm, address);
index cf8b5fdda24f39165450f57c14612fc4017dc746..3e26b800602025941532bbcd429e870fa6498b5b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/block/cs5530.c                Version 0.2     Jan 30, 2000
+ * linux/drivers/block/cs5530.c                Version 0.5     Feb 13, 2000
  *
  * Copyright (C) 2000                  Mark Lord <mlord@pobox.com>
  * May be copied or modified under the terms of the GNU General Public License
@@ -285,8 +285,6 @@ static int cs5530_config_dma (ide_drive_t *drive)
        }
        outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */
 
-       if (!strcmp(drive->name, "hdc"))        /* FIXME */
-               return 0;
        /*
         * Finally, turn DMA on in software, and exit.
         */
index 73ad0368a12eec701ea33390ef71b681482ab03b..b61767c5f2dd78c25c5365a7b842dc9a0f973437 100644 (file)
 #include <linux/in.h>
 #include <linux/malloc.h>
 #include <linux/ioport.h>
+#include <linux/spinlock.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -374,7 +375,7 @@ static inline unsigned int send_pcb_fast(unsigned int base_addr, unsigned char b
 static inline void prime_rx(struct net_device *dev)
 {
        elp_device *adapter = dev->priv;
-       while (adapter->rx_active < ELP_RX_PCBS && dev->start) {
+       while (adapter->rx_active < ELP_RX_PCBS && test_bit(LINK_STATE_START, &dev->state)) {
                if (!start_receive(dev, &adapter->itx_pcb))
                        break;
        }
@@ -672,23 +673,10 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
        elp_device *adapter;
        int timeout;
 
-       if (irq < 0 || irq > 15) {
-               printk("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq);
-               return;
-       }
        dev = dev_id;
-
-       if (dev == NULL) {
-               printk("elp_interrupt(): irq %d for unknown device.\n", irq);
-               return;
-       }
        adapter = (elp_device *) dev->priv;
-
-       if (dev->interrupt) {
-               printk("%s: re-entering the interrupt handler!\n", dev->name);
-               return;
-       }
-       dev->interrupt = 1;
+       
+       spin_lock(&adapter->lock);
 
        do {
                /*
@@ -702,20 +690,19 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                                printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
                        }
 
-                       outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR),
-                                    dev);
+                       outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
                        if (adapter->current_dma.direction) {
                                dev_kfree_skb_irq(adapter->current_dma.skb);
                        } else {
                                struct sk_buff *skb = adapter->current_dma.skb;
                                if (skb) {
-                                 if (adapter->current_dma.target) {
-                                   /* have already done the skb_put() */
-                                   memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
-                                 }
-                                 skb->protocol = eth_type_trans(skb,dev);
-                                 adapter->stats.rx_bytes += skb->len;
-                                 netif_rx(skb);
+                                       if (adapter->current_dma.target) {
+                                       /* have already done the skb_put() */
+                                       memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
+                                       }
+                                       skb->protocol = eth_type_trans(skb,dev);
+                                       adapter->stats.rx_bytes += skb->len;
+                                       netif_rx(skb);
                                }
                        }
                        adapter->dmaing = 0;
@@ -733,15 +720,14 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                        check_3c505_dma(dev);
                }
 
-               sti();
-
                /*
                 * receive a PCB from the adapter
                 */
                timeout = jiffies + 3*HZ/100;
                while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
                        if (receive_pcb(dev, &adapter->irx_pcb)) {
-                               switch (adapter->irx_pcb.command) {
+                               switch (adapter->irx_pcb.command) 
+                               {
                                case 0:
                                        break;
                                        /*
@@ -750,19 +736,15 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                                case 0xff:
                                case CMD_RECEIVE_PACKET_COMPLETE:
                                        /* if the device isn't open, don't pass packets up the stack */
-                                       if (dev->start == 0)
+                                       if (test_bit(LINK_STATE_START, &dev->state) == 0)
                                                break;
-                                       cli();
                                        len = adapter->irx_pcb.data.rcv_resp.pkt_len;
                                        dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
                                        if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
-                                               printk("%s: interrupt - packet not received correctly\n", dev->name);
-                                               sti();
+                                               printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name);
                                        } else {
                                                if (elp_debug >= 3) {
-                                                       sti();
                                                        printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
-                                                       cli();
                                                }
                                                if (adapter->irx_pcb.command == 0xff) {
                                                        if (elp_debug >= 2)
@@ -772,7 +754,6 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                                                } else {
                                                        receive_packet(dev, dlen);
                                                }
-                                               sti();
                                                if (elp_debug >= 3)
                                                        printk("%s: packet received\n", dev->name);
                                        }
@@ -839,7 +820,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                                case CMD_TRANSMIT_PACKET_COMPLETE:
                                        if (elp_debug >= 3)
                                                printk("%s: interrupt - packet sent\n", dev->name);
-                                       if (dev->start == 0)
+                                       if (test_bit(LINK_STATE_START, &dev->state) == 0)
                                                break;
                                        switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
                                        case 0xffff:
@@ -851,8 +832,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
                                                printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
                                                break;
                                        }
-                                       dev->tbusy = 0;
-                                       mark_bh(NET_BH);
+                                       netif_wake_queue(dev);
                                        break;
 
                                        /*
@@ -875,7 +855,7 @@ static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
        /*
         * indicate no longer in interrupt routine
         */
-       dev->interrupt = 0;
+       spin_unlock(&adapter->lock);
 }
 
 
@@ -912,16 +892,6 @@ static int elp_open(struct net_device *dev)
        inb_command(dev->base_addr);
        adapter_reset(dev);
 
-       /*
-        * interrupt routine not entered
-        */
-       dev->interrupt = 0;
-
-       /*
-        *  transmitter not busy
-        */
-       dev->tbusy = 0;
-
        /*
         * no receive PCBs active
         */
@@ -931,6 +901,8 @@ static int elp_open(struct net_device *dev)
        adapter->send_pcb_semaphore = 0;
        adapter->rx_backlog.in = 0;
        adapter->rx_backlog.out = 0;
+       
+       spin_lock_init(&adapter->lock);
 
        /*
         * install our interrupt service routine
@@ -1008,8 +980,8 @@ static int elp_open(struct net_device *dev)
        /*
         * device is now officially open!
         */
-       dev->start = 1;
 
+       netif_wake_queue(dev);
        MOD_INC_USE_COUNT;
 
        return 0;               /* Always succeed */
@@ -1085,6 +1057,25 @@ static int send_packet(struct net_device *dev, struct sk_buff *skb)
        return TRUE;
 }
 
+/*
+ *     The upper layer thinks we timed out
+ */
+static void elp_timeout(struct net_device *dev)
+{
+       unsigned long flags;
+       elp_device *adapter = dev->priv;
+       int stat;
+
+       stat = inb_status(dev->base_addr);
+       printk(KERN_WARNING "%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
+       if (elp_debug >= 1)
+               printk("%s: status %#02x\n", dev->name, stat);
+       dev->trans_start = jiffies;
+       adapter->stats.tx_dropped++;
+       netif_wake_queue(dev);
+}
+
 /******************************************************
  *
  * start the transmitter
@@ -1094,40 +1085,17 @@ static int send_packet(struct net_device *dev, struct sk_buff *skb)
 
 static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       if (dev->interrupt) {
-               printk("%s: start_xmit aborted (in irq)\n", dev->name);
-               return 1;
-       }
-
+       unsigned long flags;
+       elp_device *adapter = dev->priv;
+       
+       spin_lock_irqsave(&adapter->lock, flags);
        check_3c505_dma(dev);
 
-       /*
-        * if the transmitter is still busy, we have a transmit timeout...
-        */
-       if (dev->tbusy) {
-               elp_device *adapter = dev->priv;
-                       int tickssofar = jiffies - dev->trans_start;
-               int stat;
-
-               if (tickssofar < 1000)
-                       return 1;
-
-               stat = inb_status(dev->base_addr);
-               printk("%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");
-               if (elp_debug >= 1)
-                       printk("%s: status %#02x\n", dev->name, stat);
-               dev->trans_start = jiffies;
-               dev->tbusy = 0;
-               adapter->stats.tx_dropped++;
-       }
-
        if (elp_debug >= 3)
                printk("%s: request to send packet of length %d\n", dev->name, (int) skb->len);
 
-       if (test_and_set_bit(0, (void *) &dev->tbusy)) {
-               printk("%s: transmitter access conflict\n", dev->name);
-               return 1;
-       }
+       netif_stop_queue(dev);
+       
        /*
         * send the packet at skb->data for skb->len
         */
@@ -1135,7 +1103,7 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (elp_debug >= 2) {
                        printk("%s: failed to transmit packet\n", dev->name);
                }
-               dev->tbusy = 0;
+               spin_unlock_irqrestore(&adapter->lock, flags);
                return 1;
        }
        if (elp_debug >= 3)
@@ -1147,7 +1115,8 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
        dev->trans_start = jiffies;
 
        prime_rx(dev);
-
+       spin_unlock_irqrestore(&adapter->lock, flags);
+       netif_start_queue(dev);
        return 0;
 }
 
@@ -1166,7 +1135,7 @@ static struct net_device_stats *elp_get_stats(struct net_device *dev)
 
        /* If the device is closed, just return the latest stats we have,
           - we cannot ask from the adapter without interrupts */
-       if (!dev->start)
+       if (!test_bit(LINK_STATE_START, &dev->state))
                return &adapter->stats;
 
        /* send a get statistics command to the board */
@@ -1203,6 +1172,8 @@ static int elp_close(struct net_device *dev)
        if (elp_debug >= 3)
                printk("%s: request to close device\n", dev->name);
 
+       netif_stop_queue(dev);
+
        /* Someone may request the device statistic information even when
         * the interface is closed. The following will update the statistics
         * structure in the driver, so we'll be able to give current statistics.
@@ -1214,16 +1185,6 @@ static int elp_close(struct net_device *dev)
         */
        outb_control(0, dev);
 
-       /*
-        *  flag transmitter as busy (i.e. not available)
-        */
-       dev->tbusy = 1;
-
-       /*
-        *  indicate device is closed
-        */
-       dev->start = 0;
-
        /*
         * release the IRQ
         */
@@ -1252,10 +1213,13 @@ static void elp_set_mc_list(struct net_device *dev)
        elp_device *adapter = (elp_device *) dev->priv;
        struct dev_mc_list *dmi = dev->mc_list;
        int i;
+       unsigned long flags;
 
        if (elp_debug >= 3)
                printk("%s: request to set multicast list\n", dev->name);
 
+       spin_lock_irqsave(&adapter->lock, flags);
+       
        if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
                /* send a "load multicast list" command to the board, max 10 addrs/cmd */
                /* if num_addrs==0 the list will be cleared */
@@ -1291,9 +1255,13 @@ static void elp_set_mc_list(struct net_device *dev)
        adapter->tx_pcb.length = 2;
        adapter->got[CMD_CONFIGURE_82586] = 0;
        if (!send_pcb(dev, &adapter->tx_pcb))
+       {
+               spin_unlock_irqrestore(&lp->lock, flags);
                printk("%s: couldn't send 82586 configure command\n", dev->name);
+       }
        else {
                int timeout = jiffies + TIMEOUT;
+               spin_unlock_irqrestore(&lp->lock, flags);
                while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
                if (time_after_eq(jiffies, timeout))
                        TIMEOUT_MSG(__LINE__);
@@ -1313,10 +1281,12 @@ static inline void elp_init(struct net_device *dev)
        /*
         * set ptrs to various functions
         */
-       dev->open = elp_open;   /* local */
-       dev->stop = elp_close;  /* local */
-       dev->get_stats = elp_get_stats;         /* local */
-       dev->hard_start_xmit = elp_start_xmit;  /* local */
+       dev->open = elp_open;                           /* local */
+       dev->stop = elp_close;                          /* local */
+       dev->get_stats = elp_get_stats;                 /* local */
+       dev->hard_start_xmit = elp_start_xmit;          /* local */
+       dev->tx_timeout = elp_timeout;                  /* local */
+       dev->watchdog_timeo = 10*HZ;
        dev->set_multicast_list = elp_set_mc_list;      /* local */
 
        /* Setup the generic properties */
index 41993d4ec1f0110fdb76d12f74c6af354f27ad90..1cbf41fae9e1c50f1199dcfcf238e63679252e90 100644 (file)
@@ -289,4 +289,5 @@ typedef struct {
 
        unsigned int rx_active;  /* number of receive PCBs */
         volatile unsigned char hcr_val;  /* what we think the HCR contains */
+        spinlock_t lock;       /* Interrupt v tx lock */
 } elp_device;
index 54ecdad60d19b9b74b6a1f7e127cacc2b86028e2..bf3350a85e7f7ae7efaf31dabc8f0b1778ae42a0 100644 (file)
@@ -73,7 +73,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       fi
       tristate '    SMC Ultra support' CONFIG_ULTRA
       tristate '    SMC Ultra32 EISA support' CONFIG_ULTRA32
-      tristate '    SMC 9194 support' CONFIG_SMC9194
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+         tristate '    SMC 9194 support' CONFIG_SMC9194
+      fi
   fi
   bool '  Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL
   if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then
@@ -90,18 +92,22 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
    bool '  Other ISA cards' CONFIG_NET_ISA
    if [ "$CONFIG_NET_ISA" = "y" ]; then
       tristate '    Cabletron E21xx support' CONFIG_E2100
-      tristate '    EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+         tristate '    EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
+      fi
       tristate '    EtherExpress 16 support' CONFIG_EEXPRESS
       tristate '    EtherExpressPro support' CONFIG_EEXPRESS_PRO
-      tristate '    FMV-181/182/183/184 support' CONFIG_FMV18X
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+         tristate '    FMV-181/182/183/184 support' CONFIG_FMV18X
+      fi
       tristate '    HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
       tristate '    HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
       tristate '    HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-        tristate '    ICL EtherTeam 16i/32 support (EXPERIMENTAL)' CONFIG_ETH16I
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+        tristate '    ICL EtherTeam 16i/32 support' CONFIG_ETH16I
       fi
       tristate '    NE2000/NE1000 support' CONFIG_NE2000
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
         tristate '    SEEQ8005 support (EXPERIMENTAL)' CONFIG_SEEQ8005
       fi
       bool '    SK_G16 support' CONFIG_SK_G16
@@ -121,7 +127,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       fi
 
       tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT
-      tristate '    CS89x0 support' CONFIG_CS89x0
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
+         tristate '    CS89x0 support' CONFIG_CS89x0
+      fi
       tristate '    Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
       tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
       tristate '    Digi Intl. RightSwitch SE-X support' CONFIG_DGRS
@@ -145,12 +153,14 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
         tristate '    Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210
         tristate '    SMC EtherPower II (EXPERIMENTAL)' CONFIG_EPIC100
+      fi
+      if [ "$CONFIG_OBSOLETE" = "y" ]; then
         bool '    Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET
       fi
    fi
    bool '  Pocket and portable adapters' CONFIG_NET_POCKET
    if [ "$CONFIG_NET_POCKET" = "y" ]; then
-      bool '    AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP
+      tristate '    AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP
       tristate '    D-Link DE600 pocket adapter support' CONFIG_DE600
       tristate '    D-Link DE620 pocket adapter support' CONFIG_DE620
    fi
@@ -237,7 +247,9 @@ comment 'Wireless LAN (non-hamradio)'
 bool 'Wireless LAN (non-hamradio)' CONFIG_NET_RADIO
 if [ "$CONFIG_NET_RADIO" = "y" ]; then
    dep_tristate '  STRIP (Metricom starmode radio IP)' CONFIG_STRIP $CONFIG_INET
-   tristate '  AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+   if [ "$CONFIG_OBSOLETE" = "y" ]; then
+      tristate '  AT&T WaveLAN & DEC RoamAbout DS support' CONFIG_WAVELAN
+   fi
    tristate '  Aironet Arlan 655 & IC2200 DS support' CONFIG_ARLAN
    tristate '  Aironet 4500/4800 series adapters' CONFIG_AIRONET4500
    dep_tristate '   Aironet 4500/4800 ISA/PCI/PNP/365 support ' CONFIG_AIRONET4500_NONCS $CONFIG_AIRONET4500
index 45da372616b04e9baa87fff07705efd1c95bca97..1f58b30c47fcf66dea770b01e6cca5b90b5f3df7 100644 (file)
@@ -16,6 +16,8 @@
                Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
        The timer-based reset code was written by Bill Carlson, wwc@super.org.
+       
+       Modular support/softnet added by Alan Cox.
 */
 
 static const char *version =
@@ -82,6 +84,7 @@ static const char *version =
 */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
@@ -101,6 +104,7 @@ static const char *version =
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
+#include <linux/spinlock.h>
 
 #include "atp.h"
 
@@ -133,9 +137,10 @@ static void get_node_ID(struct net_device *dev);
 static unsigned short eeprom_op(short ioaddr, unsigned int cmd);
 static int net_open(struct net_device *dev);
 static void hardware_init(struct net_device *dev);
+static void tx_timeout(struct net_device *dev);
 static void write_packet(short ioaddr, int length, unsigned char *packet, int mode);
 static void trigger_send(short ioaddr, int length);
-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 read_block(short ioaddr, int length, unsigned char *buffer, int data_mode);
@@ -150,8 +155,8 @@ static void set_multicast_list(struct net_device *dev);
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
-int __init 
-atp_init(struct net_device *dev)
+
+int __init atp_init(struct net_device *dev)
 {
        int *port, ports[] = {0x378, 0x278, 0x3bc, 0};
        int base_addr = dev->base_addr;
@@ -220,7 +225,7 @@ static int __init atp_probe1(struct net_device *dev, short ioaddr)
                   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
        /* Leave the hardware in a reset state. */
-    write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+       write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 
        if (net_debug)
                printk(version);
@@ -231,11 +236,10 @@ static int __init atp_probe1(struct net_device *dev, short ioaddr)
        if (dev->priv == NULL)
                return -ENOMEM;
        memset(dev->priv, 0, sizeof(struct net_local));
-
-
        {
                struct net_local *lp = (struct net_local *)dev->priv;
                lp->addr_mode = CMR2h_Normal;
+               spin_lock_init(&lp->lock);
        }
 
        /* For the ATP adapter the "if_port" is really the data transfer mode. */
@@ -245,9 +249,11 @@ static int __init atp_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->get_stats          = net_get_stats;
+       dev->set_multicast_list = set_multicast_list;
+       dev->tx_timeout         = tx_timeout;
+       dev->watchdog_timeo     = HZ/20;
 
 #ifdef TIMED_CHECKER
        del_timer(&atp_timer);
@@ -327,12 +333,12 @@ static int net_open(struct net_device *dev)
        /* The interrupt line is turned off (tri-stated) when the device isn't in
           use.  That's especially important for "attached" interfaces where the
           port or interrupt may be shared. */
+          
        if (request_irq(dev->irq, &net_interrupt, 0, "ATP", dev)) {
                return -EAGAIN;
        }
-
        hardware_init(dev);
-       dev->start = 1;
+       netif_start_queue(dev);
        return 0;
 }
 
@@ -342,11 +348,11 @@ static void hardware_init(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr = dev->base_addr;
-    int i;
+       int i;
 
        write_reg_high(ioaddr, CMR1, CMR1h_RESET);
        
-    for (i = 0; i < 6; i++)
+       for (i = 0; i < 6; i++)
                write_reg_byte(ioaddr, PAR0 + i, dev->dev_addr[i]);
 
        write_reg_high(ioaddr, CMR2, lp->addr_mode);
@@ -356,22 +362,19 @@ static void hardware_init(struct net_device *dev)
                           (read_nibble(ioaddr, CMR2_h) >> 3) & 0x0f);
        }
 
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT);
-    write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
+       write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+       write_reg_high(ioaddr, CMR1, CMR1h_RxENABLE | CMR1h_TxENABLE);
 
        /* Enable the interrupt line from the serial port. */
        outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 
        /* Unmask the interesting interrupts. */
-    write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
-    write_reg_high(ioaddr, IMR, ISRh_RxErr);
+       write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+       write_reg_high(ioaddr, IMR, ISRh_RxErr);
 
        lp->tx_unit_busy = 0;
-    lp->pac_cnt_in_tx_buf = 0;
+       lp->pac_cnt_in_tx_buf = 0;
        lp->saved_tx_size = 0;
-
-       dev->tbusy = 0;
-       dev->interrupt = 0;
 }
 
 static void trigger_send(short ioaddr, int length)
@@ -383,15 +386,15 @@ static void trigger_send(short ioaddr, int length)
 
 static void write_packet(short ioaddr, int length, unsigned char *packet, int data_mode)
 {
-    length = (length + 1) & ~1;                /* Round up to word length. */
-    outb(EOC+MAR, ioaddr + PAR_DATA);
-    if ((data_mode & 1) == 0) {
+       length = (length + 1) & ~1;             /* Round up to word length. */
+       outb(EOC+MAR, ioaddr + PAR_DATA);
+       if ((data_mode & 1) == 0) {
                /* Write the packet out, starting with the write addr. */
                outb(WrAddr+MAR, ioaddr + PAR_DATA);
                do {
                        write_byte_mode0(ioaddr, *packet++);
                } while (--length > 0) ;
-    } else {
+       } else {
                /* Write the packet out in slow mode. */
                unsigned char outbyte = *packet++;
 
@@ -405,70 +408,61 @@ static void write_packet(short ioaddr, int length, unsigned char *packet, int da
                outb(Ctrl_HNibWrite + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
                while (--length > 0)
                        write_byte_mode1(ioaddr, *packet++);
-    }
-    /* Terminate the Tx frame.  End of write: ECB. */
-    outb(0xff, ioaddr + PAR_DATA);
-    outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
+       }
+       /* Terminate the Tx frame.  End of write: ECB. */
+       outb(0xff, ioaddr + PAR_DATA);
+       outb(Ctrl_HNibWrite | Ctrl_SelData | Ctrl_IRQEN, ioaddr + PAR_CONTROL);
 }
 
-static int
-net_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void tx_timeout(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr = dev->base_addr;
+       /* If we get here, some higher level has decided we are broken. */
+       printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+                  inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
+                  :  "IRQ conflict");
+       lp->stats.tx_errors++;
+       /* Try to restart the adapter. */
+       hardware_init(dev);
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
 
-       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("%s: transmit timed out, %s?\n", dev->name,
-                          inb(ioaddr + PAR_CONTROL) & 0x10 ? "network cable problem"
-                          :  "IRQ conflict");
-               lp->stats.tx_errors++;
-               /* Try to restart the adapter. */
-               hardware_init(dev);
-               dev->tbusy=0;
-               dev->trans_start = jiffies;
-       }
+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;
+       unsigned long flags;
+       
+       netif_stop_queue(dev);
+       
+       /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
+          This sequence must not be interrupted by an incoming packet. */
+          
+       spin_lock_irqsave(&lp->lock, flags);
+       write_reg(ioaddr, IMR, 0);
+       write_reg_high(ioaddr, IMR, 0);
+       spin_unlock_irqrestore(&lp->lock, flags);
+       
+       write_packet(ioaddr, length, buf, dev->if_port);
 
-       /* 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;
-               int flags;
-
-               /* Disable interrupts by writing 0x00 to the Interrupt Mask Register.
-                  This sequence must not be interrupted by an incoming packet. */
-               save_flags(flags);
-               cli();
-               write_reg(ioaddr, IMR, 0);
-               write_reg_high(ioaddr, IMR, 0);
-               restore_flags(flags);
-
-               write_packet(ioaddr, length, buf, dev->if_port);
-
-               lp->pac_cnt_in_tx_buf++;
-               if (lp->tx_unit_busy == 0) {
-                       trigger_send(ioaddr, length);
-                       lp->saved_tx_size = 0;                          /* Redundant */
-                       lp->re_tx = 0;
+       lp->pac_cnt_in_tx_buf++;
+       if (lp->tx_unit_busy == 0) {
+               trigger_send(ioaddr, length);
+               lp->saved_tx_size = 0;                          /* Redundant */
+               lp->re_tx = 0;
                        lp->tx_unit_busy = 1;
-               } else
-                       lp->saved_tx_size = length;
-
-               dev->trans_start = jiffies;
-               /* Re-enable the LPT interrupts. */
-               write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
-               write_reg_high(ioaddr, IMR, ISRh_RxErr);
-       }
+       } else
+               lp->saved_tx_size = length;
 
+       dev->trans_start = jiffies;
+       /* Re-enable the LPT interrupts. */
+       write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
+       write_reg_high(ioaddr, IMR, ISRh_RxErr);
        dev_kfree_skb (skb);
-
        return 0;
 }
 \f
@@ -482,14 +476,10 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        int ioaddr, status, boguscount = 20;
        static int num_tx_since_rx = 0;
 
-       if (dev == NULL) {
-               printk ("ATP_interrupt(): irq %d for unknown device.\n", irq);
-               return;
-       }
-       dev->interrupt = 1;
-
        ioaddr = dev->base_addr;
        lp = (struct net_local *)dev->priv;
+       
+       spin_lock(&lp->lock);
 
        /* Disable additional spurious interrupts. */
        outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
@@ -498,10 +488,14 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        write_reg(ioaddr, CMR2, CMR2_NULL);
        write_reg(ioaddr, IMR, 0);
 
-       if (net_debug > 5) printk("%s: In interrupt ", dev->name);
-    while (--boguscount > 0) {
+       if (net_debug > 5)
+               printk("%s: In interrupt ", dev->name);
+
+       while (--boguscount > 0) 
+       {
                status = read_nibble(ioaddr, ISR);
-               if (net_debug > 5) printk("loop status %02x..", status);
+               if (net_debug > 5)
+                       printk("loop status %02x..", status);
 
                if (status & (ISR_RxOK<<3)) {
                        write_reg(ioaddr, ISR, ISR_RxOK); /* Clear the Rx interrupt. */
@@ -539,7 +533,8 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                                        break;
                                }
                                /* Attempt to retransmit. */
-                               if (net_debug > 6)  printk("attempting to ReTx");
+                               if (net_debug > 6)
+                                       printk("attempting to ReTx");
                                write_reg(ioaddr, CMR1, CMR1_ReXmit + CMR1_Xmit);
                        } else {
                                /* Finish up the transmit. */
@@ -551,8 +546,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                                        lp->re_tx = 0;
                                } else
                                        lp->tx_unit_busy = 0;
-                               dev->tbusy = 0;
-                               mark_bh(NET_BH);        /* Inform upper layers. */
+                               netif_wake_queue(dev);  /* Inform upper layers. */
                        }
                        num_tx_since_rx++;
                } else if (num_tx_since_rx > 8
@@ -568,7 +562,7 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                        break;
                } else
                        break;
-    }
+       }
 
        /* This following code fixes a rare (and very difficult to track down)
           problem where the adapter forgets its ethernet address. */
@@ -584,17 +578,17 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        }
 
        /* Tell the adapter that it can go back to using the output line as IRQ. */
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT);
+       write_reg(ioaddr, CMR2, CMR2_IRQOUT);
        /* Enable the physical interrupt line, which is sure to be low until.. */
        outb(Ctrl_SelData + Ctrl_IRQEN, ioaddr + PAR_CONTROL);
        /* .. we enable the interrupt sources. */
        write_reg(ioaddr, IMR, ISR_RxOK | ISR_TxErr | ISR_TxOK);
        write_reg_high(ioaddr, IMR, ISRh_RxErr);                        /* Hmmm, really needed? */
 
-       if (net_debug > 5) printk("exiting interrupt.\n");
-
-       dev->interrupt = 0;
-
+       if (net_debug > 5)
+               printk("exiting interrupt.\n");
+               
+       spin_unlock(&lp->lock);
        return;
 }
 
@@ -603,33 +597,17 @@ net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
    problem where the adapter forgets its ethernet address. */
 static void atp_timed_checker(unsigned long ignored)
 {
-  int i;
-  int ioaddr = atp_timed_dev->base_addr;
+       int i;
+       struct net_local *lp = (struct net_local *)atp_timed_dev->priv;
+       int ioaddr = atp_timed_dev->base_addr;
 
-  if (!atp_timed_dev->interrupt)
-       {
-         for (i = 0; i < 6; i++)
-#if 0
-               if (read_cmd_byte(ioaddr, PAR0 + i) != atp_timed_dev->dev_addr[i])
-                 {
-                       struct net_local *lp = (struct net_local *)atp_timed_dev->priv;
-                       write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
-                       if (i == 2)
-                         lp->stats.tx_errors++;
-                       else if (i == 3)
-                         lp->stats.tx_dropped++;
-                       else if (i == 4)
-                         lp->stats.collisions++;
-                       else
-                         lp->stats.rx_errors++;
-                 }
-#else
-         write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
-#endif
-       }
-  del_timer(&atp_timer);
-  atp_timer.expires = jiffies + TIMED_CHECKER;
-  add_timer(&atp_timer);
+       spin_lock(&lp->lock);
+       for (i = 0; i < 6; i++)
+               write_reg_byte(ioaddr, PAR0 + i, atp_timed_dev->dev_addr[i]);
+       spin_unlock(&lp->lock);
+       del_timer(&atp_timer);
+       atp_timer.expires = jiffies + TIMED_CHECKER;
+       add_timer(&atp_timer);
 }
 #endif
 
@@ -707,19 +685,17 @@ static void read_block(short ioaddr, int length, unsigned char *p, int data_mode
        else
                do      *p++ = read_byte_mode6(ioaddr);  while (--length > 0);
 
-    outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
+       outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
        outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
 }
 
 /* The inverse routine to net_open(). */
-static int
-net_close(struct net_device *dev)
+static int net_close(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr = dev->base_addr;
 
-       dev->tbusy = 1;
-       dev->start = 0;
+       netif_stop_queue(dev);
 
        /* Flush the Tx and disable Rx here. */
        lp->addr_mode = CMR2h_OFF;
@@ -730,7 +706,7 @@ net_close(struct net_device *dev)
        free_irq(dev->irq, dev);
 
        /* Leave the hardware in a reset state. */
-    write_reg_high(ioaddr, CMR1, CMR1h_RESET);
+       write_reg_high(ioaddr, CMR1, CMR1h_RESET);
 
        return 0;
 }
@@ -774,3 +750,27 @@ static void set_multicast_list(struct net_device *dev)
  *  tab-width: 4
  * End:
  */
+
+#ifdef MODULE
+
+static int io = 0;
+static char nullname[8] = "";
+static struct net_device atp_dev = {
+       nullname, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, atp_probe };
+       
+MODULE_PARM(io, "I/O port of the pocket adapter");
+
+int init_module(void)
+{
+       atp_dev.base_addr = io;
+       if (register_netdev(&atp_dev) != 0)
+               return -EIO;
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       unregister_netdev(&atp_dev);
+}
+
+#endif
index 8a74d44517cbfa9352519557979791141d7d0941..46801e4015cff6f3d1d0bc9d8c034cd4fc9e1ff6 100644 (file)
@@ -4,15 +4,14 @@
 
 struct net_local 
 {
-#ifdef __KERNEL__
        struct net_device_stats stats;
-#endif
        ushort saved_tx_size;
        unsigned char
        re_tx,                  /* Number of packet retransmissions. */
        tx_unit_busy,
        addr_mode,              /* Current Rx filter e.g. promiscuous, etc. */
        pac_cnt_in_tx_buf;
+       spinlock_t lock;                /* Safety lock */
 };
 
 struct rx_header {
@@ -52,8 +51,7 @@ enum page0_regs
        CMR2_h = 0x1d, 
 };
 
-enum eepage_regs
-{ PROM_CMD = 6, PROM_DATA = 7 };       /* Note that PROM_CMD is in the "high" bits. */
+enum eepage_regs { PROM_CMD = 6, PROM_DATA = 7 };      /* Note that PROM_CMD is in the "high" bits. */
 
 
 #define ISR_TxOK       0x01
index be62ef741d807448bee688176f6e13e42c3f76df..b3851ef094d3bb16137e9525098798e0a508d62c 100644 (file)
@@ -253,7 +253,7 @@ static int          dfx_close(struct net_device *dev);
 
 static void            dfx_int_pr_halt_id(DFX_board_t *bp);
 static void            dfx_int_type_0_process(DFX_board_t *bp);
-static void            dfx_int_common(DFX_board_t *bp);
+static void            dfx_int_common(struct net_device *dev);
 static void            dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 
 static struct          net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
@@ -272,7 +272,7 @@ static void         dfx_rcv_init(DFX_board_t *bp);
 static void            dfx_rcv_queue_process(DFX_board_t *bp);
 
 static int             dfx_xmt_queue_pkt(struct sk_buff *skb, struct net_device *dev);
-static void            dfx_xmt_done(DFX_board_t *bp);
+static int             dfx_xmt_done(DFX_board_t *bp);
 static void            dfx_xmt_flush(DFX_board_t *bp);
 
 /* Define module-wide (static) variables */
@@ -1423,9 +1423,7 @@ int dfx_open(
 
        /* Set device structure info */
 
-       dev->tbusy                      = 0;
-       dev->interrupt          = DFX_UNMASK_INTERRUPTS;
-       dev->start                      = 1;
+       netif_start_queue(dev);
        return(0);
        }
 
@@ -1511,9 +1509,8 @@ int dfx_close(
 
        /* Clear device structure flags */
 
-       dev->start = 0;
-       dev->tbusy = 1;
-
+       netif_stop_queue(dev);
+       
        /* Deregister (free) IRQ */
 
        free_irq(dev->irq, dev);
@@ -1804,16 +1801,15 @@ void dfx_int_type_0_process(
  *   or updating completion indices.
  */
 
-void dfx_int_common(
-       DFX_board_t     *bp
-       )
-
-       {
+void dfx_int_common(struct net_device *dev)
+{
+       DFX_board_t     *bp = (DFX_board_t *) dev->priv;
        PI_UINT32       port_status;            /* Port Status register */
 
        /* Process xmt interrupts - frequent case, so always call this routine */
 
-       dfx_xmt_done(bp);                               /* free consumed xmt packets */
+       if(dfx_xmt_done(bp))                            /* free consumed xmt packets */
+               netif_wake_queue(dev);
 
        /* Process rcv interrupts - frequent case, so always call this routine */
 
@@ -1889,21 +1885,12 @@ void dfx_interrupt(
 
        /* Get board pointer only if device structure is valid */
 
-       if (dev == NULL)
-               {
-               printk("dfx_interrupt(): irq %d for unknown device!\n", irq);
-               return;
-               }
        bp = (DFX_board_t *) dev->priv;
 
        spin_lock(&bp->lock);
        
        /* See if we're already servicing an interrupt */
 
-       if (dev->interrupt)
-               printk("%s: Re-entering the interrupt handler!\n", dev->name);
-       dev->interrupt = DFX_MASK_INTERRUPTS;   /* ensure non reentrancy */
-
        /* Service adapter interrupts */
 
        if (bp->bus_type == DFX_BUS_TYPE_PCI)
@@ -1914,7 +1901,7 @@ void dfx_interrupt(
 
                /* Call interrupt service routine for this adapter */
 
-               dfx_int_common(bp);
+               dfx_int_common(dev);
 
                /* Clear PDQ interrupt status bit and reenable interrupts */
 
@@ -1932,7 +1919,7 @@ void dfx_interrupt(
 
                /* Call interrupt service routine for this adapter */
 
-               dfx_int_common(bp);
+               dfx_int_common(dev);
 
                /* Reenable interrupts at the ESIC */
 
@@ -1941,7 +1928,6 @@ void dfx_interrupt(
                dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
                }
 
-       dev->interrupt = DFX_UNMASK_INTERRUPTS;
        spin_unlock(&bp->lock);
        return;
        }
@@ -3199,6 +3185,8 @@ int dfx_xmt_queue_pkt(
        XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
        unsigned long           flags;
 
+       netif_stop_queue(dev);
+       
        /*
         * Verify that incoming transmit request is OK
         *
@@ -3213,7 +3201,7 @@ int dfx_xmt_queue_pkt(
                printk("%s: Invalid packet length - %u bytes\n", 
                        dev->name, skb->len);
                bp->xmt_length_errors++;                /* bump error counter */
-               mark_bh(NET_BH);
+               netif_wake_queue(dev);
                dev_kfree_skb(skb);
                return(0);                              /* return "success" */
        }
@@ -3237,6 +3225,7 @@ int dfx_xmt_queue_pkt(
                        {
                        bp->xmt_discards++;                                     /* bump error counter */
                        dev_kfree_skb(skb);             /* free sk_buff now */
+                       netif_wake_queue(dev);
                        return(0);                                                      /* return "success" */
                        }
                }
@@ -3339,6 +3328,7 @@ int dfx_xmt_queue_pkt(
        bp->rcv_xmt_reg.index.xmt_prod = prod;
        dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
        spin_unlock_irqrestore(&bp->lock, flags);
+       netif_wake_queue(dev);
        return(0);                                                      /* packet queued to adapter */
        }
 
@@ -3375,13 +3365,14 @@ int dfx_xmt_queue_pkt(
  *   None
  */
 
-void dfx_xmt_done(
+int dfx_xmt_done(
        DFX_board_t *bp
        )
 
        {
        XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
        PI_TYPE_2_CONSUMER      *p_type_2_cons;         /* ptr to rcv/xmt consumer block register */
+       int                     freed = 0;              /* buffers freed */
 
        /* Service all consumed transmit frames */
 
@@ -3413,8 +3404,9 @@ void dfx_xmt_done(
                 */
 
                bp->rcv_xmt_reg.index.xmt_comp += 1;
+               freed++;
                }
-       return;
+       return freed;
        }
 
 \f
index 63b5405007f6ee00d803dd4eaa2028379dfb6c81..9de74e1b664a9459da8a31888c38789ccd0410bc 100644 (file)
@@ -1,7 +1,9 @@
-/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
 /*
-   NOTICE: this version tested with kernels 1.3.72 and later only!
+
+        drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux
+
        Written 1996-1999 by Donald Becker.
+       Modified 2000 by Linux Kernel Team
 
        This software may be used and distributed according to the terms
        of the GNU Public License, incorporated herein by reference.
                http://cesdis.gsfc.nasa.gov/linux/misc/modules.html
        There is a Majordomo mailing list based at
                linux-eepro100@cesdis.gsfc.nasa.gov
-*/
-
-static const char *version =
-"eepro100.c:v1.09j 7/27/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
-
-/* A few user-configurable values that apply to all boards.
-   First set is undocumented and spelled per Intel recommendations. */
-
-static int congenb = 0;                /* Enable congestion control in the DP83840. */
-static int txfifo = 8;         /* Tx FIFO threshold in 4 byte units, 0-15 */
-static int rxfifo = 8;         /* Rx FIFO threshold, default 32 bytes. */
-/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
-static int txdmacount = 128;
-static int rxdmacount = 0;
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
-   Lower values use more memory, but are faster. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
-
-/* 'options' is used to pass a transceiver override or full-duplex flag
-   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int debug = -1;                 /* The debug level */
-
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE   32              /* Effectively 2 entries fewer. */
-#define RX_RING_SIZE   32
-/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */
-#define TX_QUEUE_LIMIT  12
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (2*HZ)
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ             1536
-
-#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
-#warning  You must compile this file with the correct options!
-#warning  See the last lines of the source file.
-#error You must compile this driver with "-O".
-#endif
-
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/malloc.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
 
-MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
-MODULE_PARM(congenb, "i");
-MODULE_PARM(txfifo, "i");
-MODULE_PARM(rxfifo, "i");
-MODULE_PARM(txdmacount, "i");
-MODULE_PARM(rxdmacount, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(multicast_filter_limit, "i");
 
-#define RUN_AT(x) (jiffies + (x))
 
+   Version history:
+       v1.09j+LK1.0 - Jeff Garzik <jgarzik@mandrakesoft.com>
+               Convert to new PCI driver interface
 
-/* The total I/O port extent of the board.
-   The registers beyond 0x18 only exist on the i82558. */
-#define SPEEDO3_TOTAL_SIZE 0x20
 
-int speedo_debug = 1;
 
-/*
                                Theory of Operation
 
 I. Board Compatibility
@@ -246,32 +162,108 @@ having to sign an Intel NDA when I'm helping Intel sell their own product!
 
 */
 
-/* This table drives the PCI probe routines. */
-static struct net_device *speedo_found1(struct pci_dev *pdev, long ioaddr,
-                                       int irq, int chip_idx, int fnd_cnt);
 
-#ifdef USE_IO
-#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_IO|PCI_ADDR1
-#define SPEEDO_SIZE            32
-#else
-#define SPEEDO_IOTYPE   PCI_USES_MASTER|PCI_USES_MEM|PCI_ADDR0
-#define SPEEDO_SIZE            0x1000
+static const char *version =
+"eepro100.c:v1.09j+LK1.0 Feb 13, 2000  Linux Kernel Team  http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n";
+
+/* A few user-configurable values that apply to all boards.
+   First set is undocumented and spelled per Intel recommendations. */
+
+static int congenb = 0;                /* Enable congestion control in the DP83840. */
+static int txfifo = 8;         /* Tx FIFO threshold in 4 byte units, 0-15 */
+static int rxfifo = 8;         /* Rx FIFO threshold, default 32 bytes. */
+/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
+static int txdmacount = 128;
+static int rxdmacount = 0;
+
+/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
+   Lower values use more memory, but are faster. */
+static int rx_copybreak = 200;
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
+static int multicast_filter_limit = 64;
+
+/* 'options' is used to pass a transceiver override or full-duplex flag
+   e.g. "options=16" for FD, "options=32" for 100mbps-only. */
+#if MODULE_SETUP_FIXED
+static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+#endif
+static int debug = -1;                 /* The debug level */
+
+/* A few values that may be tweaked. */
+/* The ring sizes should be a power of two for efficiency. */
+#define TX_RING_SIZE   32              /* Effectively 2 entries fewer. */
+#define RX_RING_SIZE   32
+/* Actual number of TX packets queued, must be <= TX_RING_SIZE-2. */
+#define TX_QUEUE_LIMIT  12
+
+/* Operational parameters that usually are not changed. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
+#define PKT_BUF_SZ             1536
+
+#if !defined(__OPTIMIZE__)  ||  !defined(__KERNEL__)
+#warning  You must compile this file with the correct options!
+#warning  See the last lines of the source file.
+#error You must compile this driver with "-O".
 #endif
 
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+
+MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
+MODULE_DESCRIPTION("Intel i82557/i82558 PCI EtherExpressPro driver");
+MODULE_PARM(debug, "i");
+
+#if MODULE_OPTIONS_FIXED
+MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
+#endif
+
+MODULE_PARM(congenb, "i");
+MODULE_PARM(txfifo, "i");
+MODULE_PARM(rxfifo, "i");
+MODULE_PARM(txdmacount, "i");
+MODULE_PARM(rxdmacount, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(multicast_filter_limit, "i");
+
+#define EEPRO100_MODULE_NAME "eepro100"
+#define PFX EEPRO100_MODULE_NAME ": "
+
+#define RUN_AT(x) (jiffies + (x))
+
+int speedo_debug = 1;
+
+
 enum pci_flags_bit {
        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
        PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
 };
-struct pci_id_info {
-       const char *name;
-       u16     vendor_id, device_id, device_id_mask, flags;
-       int io_size;
-       struct net_device *(*probe1)(struct pci_dev *pdev, long ioaddr, int irq, int chip_idx, int fnd_cnt);
-} static pci_tbl[] = {
-       { "Intel PCI EtherExpress Pro100",
-         0x8086, 0x1229, 0xffff, PCI_USES_IO|PCI_USES_MASTER, 32, speedo_found1 },
-       {0,},                                           /* 0 terminated list. */
-};
 
 #ifndef USE_IO
 #define inb readb
@@ -323,54 +315,75 @@ enum commands {
 #endif
 
 enum SCBCmdBits {
-     SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
-     SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
-     SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
-     /* The rest are Rx and Tx commands. */
-     CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
-     CUCmdBase=0x0060,  /* CU Base address (set to zero) . */
-     CUDumpStats=0x0070, /* Dump then reset stats counters. */
-     RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
-     RxResumeNoResources=0x0007,
+       SCBMaskCmdDone = 0x8000,
+       SCBMaskRxDone = 0x4000,
+       SCBMaskCmdIdle = 0x2000,
+       SCBMaskRxSuspend = 0x1000,
+       SCBMaskEarlyRx = 0x0800,
+       SCBMaskFlowCtl = 0x0400,
+       SCBTriggerIntr = 0x0200,
+       SCBMaskAll = 0x0100,
+       /* The rest are Rx and Tx commands. */
+       CUStart = 0x0010,
+       CUResume = 0x0020,
+       CUStatsAddr = 0x0040,
+       CUShowStats = 0x0050,
+       CUCmdBase = 0x0060,     /* CU Base address (set to zero) . */
+       CUDumpStats = 0x0070,   /* Dump then reset stats counters. */
+       RxStart = 0x0001,
+       RxResume = 0x0002,
+       RxAbort = 0x0004,
+       RxAddrLoad = 0x0006,
+       RxResumeNoResources = 0x0007,
 };
 
 enum SCBPort_cmds {
-       PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
+       PortReset = 0,
+       PortSelfTest = 1,
+       PortPartialReset = 2,
+       PortDump = 3,
 };
 
 /* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor {                    /* A generic descriptor. */
-       s32 cmd_status;                 /* All command and status fields. */
-       u32 link;                                       /* struct descriptor *  */
+struct descriptor {            /* A generic descriptor. */
+       s32 cmd_status;         /* All command and status fields. */
+       u32 link;               /* struct descriptor *  */
        unsigned char params[0];
 };
 
 /* The Speedo3 Rx and Tx buffer descriptors. */
-struct RxFD {                                  /* Receive frame descriptor. */
+struct RxFD {                  /* Receive frame descriptor. */
        s32 status;
-       u32 link;                                       /* struct RxFD * */
-       u32 rx_buf_addr;                        /* void * */
+       u32 link;               /* struct RxFD * */
+       u32 rx_buf_addr;        /* void * */
        u32 count;
 };
 
 /* Selected elements of the Tx/RxFD.status word. */
 enum RxFD_bits {
-       RxComplete=0x8000, RxOK=0x2000,
-       RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
-       RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
-       TxUnderrun=0x1000,  StatusComplete=0x8000,
+       RxComplete = 0x8000,
+       RxOK = 0x2000,
+       RxErrCRC = 0x0800,
+       RxErrAlign = 0x0400,
+       RxErrTooBig = 0x0200,
+       RxErrSymbol = 0x0010,
+       RxEth2Type = 0x0020,
+       RxNoMatch = 0x0004,
+       RxNoIAMatch = 0x0002,
+       TxUnderrun = 0x1000,
+       StatusComplete = 0x8000,
 };
 
-struct TxFD {                                  /* Transmit frame descriptor set. */
+struct TxFD {                  /* Transmit frame descriptor set. */
        s32 status;
-       u32 link;                                       /* void * */
-       u32 tx_desc_addr;                       /* Always points to the tx_buf_addr element. */
-       s32 count;                                      /* # of TBD (=1), Tx start thresh., etc. */
+       u32 link;               /* void * */
+       u32 tx_desc_addr;       /* Always points to the tx_buf_addr element. */
+       s32 count;              /* # of TBD (=1), Tx start thresh., etc. */
        /* This constitutes two "TBD" entries -- we only use one. */
-       u32 tx_buf_addr0;                       /* void *, frame to be transmitted.  */
-       s32 tx_buf_size0;                       /* Length of Tx frame. */
-       u32 tx_buf_addr1;                       /* void *, frame to be transmitted.  */
-       s32 tx_buf_size1;                       /* Length of Tx frame. */
+       u32 tx_buf_addr0;       /* void *, frame to be transmitted.  */
+       s32 tx_buf_size0;       /* Length of Tx frame. */
+       u32 tx_buf_addr1;       /* void *, frame to be transmitted.  */
+       s32 tx_buf_size1;       /* Length of Tx frame. */
 };
 
 /* Elements of the dump_statistics block. This block must be lword aligned. */
@@ -397,46 +410,43 @@ struct speedo_stats {
 /* Do not change the position (alignment) of the first few elements!
    The later elements are grouped for cache locality. */
 struct speedo_private {
-       struct TxFD     *tx_ring;               /* Commands (usually CmdTxPacket). */
-       struct RxFD *rx_ringp[RX_RING_SIZE];    /* Rx descriptor, used as ring. */
+       struct TxFD *tx_ring;           /* Commands (usually CmdTxPacket). */
+       struct RxFD *rx_ringp[RX_RING_SIZE];/* Rx descriptor, used as ring. */
        /* The addresses of a Tx/Rx-in-place packets/buffers. */
-       struct sk_bufftx_skbuff[TX_RING_SIZE];
-       struct sk_buffrx_skbuff[RX_RING_SIZE];
-       dma_addr_t      rx_ring_dma[RX_RING_SIZE];
-       dma_addr_t      tx_ring_dma;
-       struct descriptor  *last_cmd;   /* Last command sent. */
+       struct sk_buff *tx_skbuff[TX_RING_SIZE];
+       struct sk_buff *rx_skbuff[RX_RING_SIZE];
+       dma_addr_t rx_ring_dma[RX_RING_SIZE];
+       dma_addr_t tx_ring_dma;
+       struct descriptor *last_cmd;    /* Last command sent. */
        unsigned int cur_tx, dirty_tx;  /* The ring entries to be free()ed. */
-       spinlock_t lock;                                /* Group with Tx control cache line. */
-       u32 tx_threshold;                                       /* The value for txdesc.count. */
-       struct RxFD *last_rxf;  /* Last command sent. */
-       unsigned int cur_rx, dirty_rx;          /* The next free ring entry */
-       long last_rx_time;                      /* Last Rx, in jiffies, to handle Rx hang. */
+       spinlock_t lock;                /* Group with Tx control cache line. */
+       u32 tx_threshold;               /* The value for txdesc.count. */
+       struct RxFD *last_rxf;          /* Last command sent. */
+       unsigned int cur_rx, dirty_rx;  /* The next free ring entry */
+       long last_rx_time;              /* Last Rx, in jiffies, to handle Rx hang. */
        const char *product_name;
-       struct net_device *next_module;
-       void *priv_addr;                                        /* Unaligned address for kfree */
        struct enet_statistics stats;
        struct speedo_stats *lstats;
        int chip_id;
        unsigned char acpi_pwr;
        struct pci_dev *pdev;
        struct timer_list timer;        /* Media selection timer. */
-       int mc_setup_frm_len;                           /* The length of an allocated.. */
-       struct descriptor *mc_setup_frm;        /* ..multicast setup frame. */
-       int mc_setup_busy;                                      /* Avoid double-use of setup frame. */
+       int mc_setup_frm_len;           /* The length of an allocated.. */
+       struct descriptor *mc_setup_frm;/* ..multicast setup frame. */
+       int mc_setup_busy;              /* Avoid double-use of setup frame. */
        dma_addr_t mc_setup_dma;
-       char rx_mode;                                           /* Current PROMISC/ALLMULTI setting. */
-       unsigned int tx_full:1;                         /* The Tx queue is full. */
-       unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
-       unsigned int flow_ctrl:1;                       /* Use 802.3x flow control. */
-       unsigned int rx_bug:1;                          /* Work around receiver hang errata. */
-       unsigned int rx_bug10:1;                        /* Receiver might hang at 10mbps. */
-       unsigned int rx_bug100:1;                       /* Receiver might hang at 100mbps. */
-       unsigned char default_port:8;           /* Last dev->if_port value. */
-       unsigned short phy[2];                          /* PHY media interfaces available. */
-       unsigned short advertising;                     /* Current PHY advertised caps. */
-       unsigned short partner;                         /* Link partner caps. */
+       char rx_mode;                   /* Current PROMISC/ALLMULTI setting. */
+       unsigned int tx_full:1;         /* The Tx queue is full. */
+       unsigned int full_duplex:1;     /* Full-duplex operation requested. */
+       unsigned int flow_ctrl:1;       /* Use 802.3x flow control. */
+       unsigned int rx_bug:1;          /* Work around receiver hang errata. */
+       unsigned int rx_bug10:1;        /* Receiver might hang at 10mbps. */
+       unsigned int rx_bug100:1;       /* Receiver might hang at 100mbps. */
+       unsigned char default_port:8;   /* Last dev->if_port value. */
+       unsigned short phy[2];          /* PHY media interfaces available. */
+       unsigned short advertising;     /* Current PHY advertised caps. */
+       unsigned short partner;         /* Link partner caps. */
 };
-
 /* The parameters for a CmdConfigure operation.
    There are so many options that it would be difficult to document each bit.
    We mostly use the default or recommended settings. */
@@ -487,62 +497,10 @@ static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
                                                   0x2000, 0x2100, 0x0400, 0x3100};
 #endif
 
-/* A list of all installed Speedo devices, for removing the driver module. */
-static struct net_device *root_speedo_dev = NULL;
-
-static int __init eepro100_init (void)
-{
-       int cards_found = 0;
-       struct pci_dev *pdev = NULL;
-       long ioaddr;
-       int irq;
-
-       while ((pdev = pci_find_device (PCI_VENDOR_ID_INTEL,
-                                       PCI_DEVICE_ID_INTEL_82557, pdev))) {
-#ifdef USE_IO
-               ioaddr = pdev->resource[1].start;
-#else
-               ioaddr = pdev->resource[0].start;
-#endif
-               irq = pdev->irq;
-
-               /* Remove I/O space marker in bit 0. */
-#ifdef USE_IO
-               if (check_region(ioaddr, 32)) {
-                       printk(KERN_ERR "eepro100: %ld mem region busy\n", ioaddr);
-                       continue;
-               }
-#else
-               {
-                       unsigned long orig_ioaddr = ioaddr;
-                       
-                       if (check_mem_region(ioaddr, 32)) {
-                               printk(KERN_ERR "eepro100: %ld mem region busy\n",
-                                      ioaddr);
-                               continue;
-                       }
-
-                       if ((ioaddr = (long)ioremap(orig_ioaddr, 0x1000)) == 0) {
-                               printk(KERN_INFO "Failed to map PCI address %#lx.\n",
-                                          orig_ioaddr);
-                               continue;
-                       }
-               }
-#endif
-               if (speedo_debug > 2)
-                       printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n",
-                                  ioaddr, irq);
-
-               if(speedo_found1(pdev, ioaddr, irq, 0,cards_found))
-                       cards_found++;
-       }
-
-       return cards_found;
-}
 
 
-static struct net_device *speedo_found1(struct pci_dev *pdev,
-                         long ioaddr, int irq, int chip_idx, int card_idx)
+static int __devinit eepro100_init_one (struct pci_dev *pdev,
+                                       const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct speedo_private *sp;
@@ -551,31 +509,68 @@ static struct net_device *speedo_found1(struct pci_dev *pdev,
        const char *product;
        int i, option;
        u16 eeprom[0x100];
-       int acpi_idle_state = 0, pm;
+       int acpi_idle_state = 0, pm, irq;
+       unsigned long ioaddr;
 
        static int did_version = 0;                     /* Already printed version info. */
+
+#ifdef USE_IO
+       ioaddr = pci_resource_start (pdev, 0);
+#else
+       ioaddr = pci_resource_start (pdev, 1);
+#endif
+       irq = pdev->irq;
+       
+       if (!request_region (pci_resource_start (pdev, 1),
+                            pci_resource_len (pdev, 1),
+                            EEPRO100_MODULE_NAME)) {
+               printk (KERN_ERR PFX "cannot reserve I/O ports\n");
+               goto err_out_none;
+       }
+       if (!request_mem_region (pci_resource_start (pdev, 0),
+                                pci_resource_len (pdev, 0),
+                                EEPRO100_MODULE_NAME)) {
+               printk (KERN_ERR PFX "cannot reserve MMIO region\n");
+               goto err_out_free_pio_region;
+       }
+       
+#ifndef USE_IO
+       ioaddr = (unsigned long) ioremap (pci_resource_start (pdev, 0),
+                                         pci_resource_len (pdev, 0));
+       if (!ioaddr) {
+               printk (KERN_ERR PFX "cannot remap MMIO region %lx @ %lx\n",
+                       pci_resource_len (pdev, 0),
+                       pci_resource_start (pdev, 0));
+               goto err_out_free_mmio_region;
+       }
+#endif
+
        if (speedo_debug > 0  &&  did_version++ == 0)
                printk(version);
 
        tx_ring = pci_alloc_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
                                             + sizeof(struct speedo_stats), &tx_ring_dma);
        if (!tx_ring) {
-               printk(KERN_ERR "Could not allocate DMA memory.\n");
-               return NULL;
+               printk(KERN_ERR PFX "Could not allocate DMA memory.\n");
+               goto err_out_iounmap;
        }
 
        dev = init_etherdev(NULL, sizeof(struct speedo_private));
        if (dev == NULL) {
-               pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
-                                         + sizeof(struct speedo_stats),
-                                   tx_ring, tx_ring_dma);
-               return NULL;
+               printk(KERN_ERR PFX "Could not allocate ethernet device.\n");
+               goto err_out_free_tx_ring;
+       }
+       if (dev->priv == NULL) {
+               printk(KERN_ERR PFX "Could not allocate ethernet device private info.\n");
+               goto err_out_free_netdev;
        }
 
        if (dev->mem_start > 0)
                option = dev->mem_start;
+#if MODULE_SETUP_FIXED
        else if (card_idx >= 0  &&  options[card_idx] >= 0)
                option = options[card_idx];
+#endif
        else
                option = 0;
 
@@ -634,7 +629,7 @@ static struct net_device *speedo_found1(struct pci_dev *pdev,
        if (eeprom[3] & 0x0100)
                product = "OEM i82557/i82558 10/100 Ethernet";
        else
-               product = pci_tbl[chip_idx].name;
+               product = "Intel PCI EtherExpress Pro100";
 
        printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr);
 
@@ -715,37 +710,27 @@ static struct net_device *speedo_found1(struct pci_dev *pdev,
        /* Return the chip to its original power state. */
        pci_set_power_state (pdev, acpi_idle_state);
 
-#ifdef USE_IO
-       request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet");
-#else
-       request_mem_region(ioaddr, 0x1000, "Intel Speedo3 Ethernet");
-#endif
-
        dev->base_addr = ioaddr;
        dev->irq = irq;
 
        sp = dev->priv;
-       if (dev->priv == NULL) {
-               void *mem = kmalloc(sizeof(*sp), GFP_KERNEL);
-               dev->priv = sp = mem;           /* Cache align here if kmalloc does not. */
-               sp->priv_addr = mem;
-       }
        memset(sp, 0, sizeof(*sp));
-       sp->next_module = root_speedo_dev;
-       root_speedo_dev = dev;
 
        sp->pdev = pdev;
-       sp->chip_id = chip_idx;
        sp->acpi_pwr = acpi_idle_state;
        sp->tx_ring = (struct TxFD *)tx_ring;
        sp->tx_ring_dma = tx_ring_dma;
        sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
        
        sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
+
+#if MODULE_SETUP_FIXED
        if (card_idx >= 0) {
                if (full_duplex[card_idx] >= 0)
                        sp->full_duplex = full_duplex[card_idx];
        }
+#endif
+
        sp->default_port = option >= 0 ? (option & 0x0f) : 0;
 
        sp->phy[0] = eeprom[6];
@@ -765,9 +750,30 @@ static struct net_device *speedo_found1(struct pci_dev *pdev,
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &speedo_ioctl;
 
-       return dev;
+       return 0;
+
+err_out_free_netdev:
+       unregister_netdevice (dev);
+       kfree (dev);
+err_out_free_tx_ring:
+       pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
+                                 + sizeof(struct speedo_stats),
+                           tx_ring, tx_ring_dma);
+err_out_iounmap:
+#ifndef USE_IO
+       iounmap ((void *)ioaddr);
+#endif
+err_out_free_mmio_region:
+       release_mem_region (pci_resource_start (pdev, 0),
+                           pci_resource_len (pdev, 0));
+err_out_free_pio_region:
+       release_region (pci_resource_start (pdev, 1),
+                       pci_resource_len (pdev, 1));
+err_out_none:
+       return -ENODEV;
 }
-\f
+
+
 /* Serial EEPROM section.
    A "bit" grungy, but we work our way through bit-by-bit :->. */
 /*  EEPROM_Ctrl bits. */
@@ -1751,47 +1757,95 @@ static void set_rx_mode(struct net_device *dev)
 }
 
 
+static void eepro100_suspend (struct pci_dev *pdev)
+{
+       struct net_device *dev = pdev->driver_data;
+       long ioaddr = dev->base_addr;
+
+       netif_stop_queue (dev);
+       outl(PortPartialReset, ioaddr + SCBPort);
+}
+
+
+static void eepro100_resume (struct pci_dev *pdev)
+{
+       struct net_device *dev = pdev->driver_data;
+       struct speedo_private *np = (struct speedo_private *)dev->priv;
+
+       speedo_resume(dev);
+       np->rx_mode = -1;
+       np->flow_ctrl = np->partner = 0;
+       set_rx_mode(dev);
+}
+
+
+static void __devexit eepro100_remove_one (struct pci_dev *pdev)
+{
+       struct net_device *dev = pdev->driver_data;
+       struct speedo_private *sp = (struct speedo_private *)dev->priv;
+       
+       unregister_netdev (dev);
+
+       release_region (pci_resource_start (pdev, 1),
+                       pci_resource_len (pdev, 1));
+       release_mem_region (pci_resource_start (pdev, 0),
+                           pci_resource_len (pdev, 0));
+
+#ifndef USE_IO
+       iounmap ((char *) dev->base_addr);
+#endif
+
+       pci_set_power_state (pdev, sp->acpi_pwr);
+
+       kfree (dev);
+}
+
+
+static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       { 0,},
+};
+MODULE_DEVICE_TABLE (pci, eepro100_pci_tbl);
+
+       
+static struct pci_driver eepro100_driver = {
+       name:           EEPRO100_MODULE_NAME,
+       id_table:       eepro100_pci_tbl,
+       probe:          eepro100_init_one,
+       remove:         eepro100_remove_one,
+       suspend:        eepro100_suspend,
+       resume:         eepro100_resume,
+};
+
+
 static int __init eepro100_init_module(void)
 {
        int cards_found;
 
        if (debug >= 0)
                speedo_debug = debug;
+
        /* Always emit the version message. */
        if (speedo_debug)
                printk(KERN_INFO "%s", version);
 
-       cards_found = eepro100_init();
+       cards_found = pci_register_driver (&eepro100_driver);
        if (cards_found <= 0) {
-               printk(KERN_INFO "eepro100: No cards found, driver not installed.\n");
+               printk(KERN_INFO PFX "No cards found, driver not installed.\n");
                return -ENODEV;
        }
+
        return 0;
 }
 
+
 static void __exit eepro100_cleanup_module(void)
 {
-       struct net_device *next_dev;
-
-       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
-       while (root_speedo_dev) {
-               struct speedo_private *sp = (void *)root_speedo_dev->priv;
-               unregister_netdev(root_speedo_dev);
-#ifdef USE_IO
-               release_region(root_speedo_dev->base_addr, SPEEDO3_TOTAL_SIZE);
-#else
-               release_mem_region(root_speedo_dev->base_addr, 0x1000);
-               iounmap((char *)root_speedo_dev->base_addr);
-#endif
-               pci_set_power_state(sp->pdev, sp->acpi_pwr);
-               next_dev = sp->next_module;
-               if (sp->priv_addr)
-                       kfree(sp->priv_addr);
-               kfree(root_speedo_dev);
-               root_speedo_dev = next_dev;
-       }
+       pci_unregister_driver (&eepro100_driver);
 }
 
+
 module_init(eepro100_init_module);
 module_exit(eepro100_cleanup_module);
 
index 7d9cd2363cb28b9e6cccc843913ce874147c9636..affd0cc3ea967d94ea39c9143e630281beee7d84 100644 (file)
@@ -424,6 +424,8 @@ static struct net_device *epic_probe1(struct pci_dev *pdev, long ioaddr, int irq
        dev->do_ioctl = &mii_ioctl;
        dev->tx_timeout = epic_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
+       
+       netif_stop_queue (dev);
 
        return dev;
 }
@@ -526,13 +528,15 @@ epic_open(struct net_device *dev)
        int mii_reg5;
        ep->full_duplex = ep->force_fd;
 
+       MOD_INC_USE_COUNT;
+
        /* Soft reset the chip. */
        outl(0x4001, ioaddr + GENCTL);
 
-       if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
-               return -EAGAIN;
-
-       MOD_INC_USE_COUNT;
+       if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev)) {
+               MOD_DEC_USE_COUNT;
+               return -EBUSY;
+       }
 
        epic_init_ring(dev);
 
@@ -580,8 +584,6 @@ epic_open(struct net_device *dev)
        set_rx_mode(dev);
        outl(0x000A, ioaddr + COMMAND);
 
-       netif_start_queue(dev);
-
        /* Enable interrupts by setting the interrupt mask. */
        outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
                 | CntFull | TxUnderrun | TxDone
@@ -594,10 +596,12 @@ epic_open(struct net_device *dev)
                           dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
                           ep->full_duplex ? "full" : "half");
 
+       netif_start_queue(dev);
+
        /* Set the timer to switch to check for link beat and perhaps switch
           to an alternate media type. */
        init_timer(&ep->timer);
-       ep->timer.expires = RUN_AT((24*HZ)/10);                 /* 2.4 sec. */
+       ep->timer.expires = RUN_AT(3*HZ);                       /* 3 sec. */
        ep->timer.data = (unsigned long)dev;
        ep->timer.function = &epic_timer;                               /* timer handler */
        add_timer(&ep->timer);
@@ -612,6 +616,8 @@ static void epic_pause(struct net_device *dev)
        long ioaddr = dev->base_addr;
        struct epic_private *ep = (struct epic_private *)dev->priv;
 
+       netif_stop_queue (dev);
+       
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x00000000, ioaddr + INTMASK);
        /* Stop the chip's Tx and Rx DMA processes. */
@@ -670,11 +676,13 @@ static void epic_restart(struct net_device *dev)
                 | CntFull | TxUnderrun | TxDone
                 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
                 ioaddr + INTMASK);
+
+       netif_start_queue (dev);
+       
        printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
                   " interrupt %4.4x.\n",
                           dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL),
                   inl(ioaddr + INTSTAT));
-       return;
 }
 
 static void epic_timer(unsigned long data)
@@ -737,7 +745,8 @@ static void epic_tx_timeout(struct net_device *dev)
 
        dev->trans_start = jiffies;
        ep->stats.tx_errors++;
-       return;
+       
+       netif_start_queue (dev);
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
@@ -789,6 +798,8 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        int entry;
        u32 flag;
 
+       netif_stop_queue (dev);
+
        /* Caution: the write order is important here, set the base address
           with the "ownership" bits last. */
 
@@ -805,13 +816,10 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        
        if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
          flag = 0x10; /* No interrupt */
-         netif_start_queue(dev);
        } else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
          flag = 0x14; /* Tx-done intr. */
-         netif_start_queue(dev);
        } else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
          flag = 0x10; /* No Tx-done intr. */
-         netif_start_queue(dev);
        } else {
          /* Leave room for two additional entries. */
          flag = 0x14; /* Tx-done intr. */
@@ -825,6 +833,10 @@ epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
        outl(0x0004, dev->base_addr + COMMAND);
 
        dev->trans_start = jiffies;
+
+       if (! ep->tx_full)
+               netif_start_queue (dev);
+
        if (epic_debug > 4)
                printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
                           "flag %2.2x Tx status %8.8x.\n",
@@ -911,8 +923,12 @@ static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                            dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
                                /* The ring is no longer full, clear tbusy. */
                                ep->tx_full = 0;
-                               netif_wake_queue (dev);
                        }
+                       
+                       if (ep->tx_full)
+                               netif_stop_queue (dev);
+                       else
+                               netif_wake_queue (dev);
 
                        ep->dirty_tx = dirty_tx;
                }
index b1af7e5dc1e313a8cab93a9922e7b84b6d7f5983..502936cab184c48a50569b1f41c6ee4257c5e175 100644 (file)
@@ -158,6 +158,8 @@ static char *version =
 #include <linux/malloc.h>                
 #include <linux/string.h>                
 #include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -168,26 +170,7 @@ static char *version =
 #include <asm/io.h>              
 #include <asm/dma.h>
 
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE >= 0x20123
-#include <linux/init.h>
-#else
-#define __init
-#define __initdata
-#endif
 
-#if LINUX_VERSION_CODE < 0x20138
-#define test_and_set_bit(val,addr) set_bit(val,addr)
-#endif
-
-#if LINUX_VERSION_CODE < 0x020100
-typedef struct enet_statistics eth16i_stats_type;
-#else
-typedef struct net_device_stats eth16i_stats_type;
-#endif
 
 /* Few macros */
 #define BIT(a)                ( (1 << (a)) )  
@@ -371,12 +354,14 @@ typedef struct net_device_stats eth16i_stats_type;
 #define RESET                  ID_ROM_0
 
 /* This is the I/O address list to be probed when seeking the card */
-static unsigned int eth16i_portlist[] =
-   { 0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 };
+static unsigned int eth16i_portlist[] = {
+       0x260, 0x280, 0x2A0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 
+};
 
-static unsigned int eth32i_portlist[] =
-   { 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
-     0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 };
+static unsigned int eth32i_portlist[] = { 
+       0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000, 0x8000,
+       0x9000, 0xA000, 0xB000, 0xC000, 0xD000, 0xE000, 0xF000, 0 
+};
 
 /* This is the Interrupt lookup table for Eth16i card */
 static unsigned int eth16i_irqmap[] = { 9, 10, 5, 15, 0 };
@@ -399,7 +384,7 @@ static unsigned int eth16i_debug = ETH16I_DEBUG;
 /* Information for each board */
 
 struct eth16i_local {
-       eth16i_stats_type stats;
+       struct net_device_stats stats;
        unsigned char     tx_started;
        unsigned char     tx_buf_busy;
        unsigned short    tx_queue;  /* Number of packets in transmit buffer */
@@ -409,6 +394,7 @@ struct eth16i_local {
        unsigned long     tx_buffered_packets;
        unsigned long     tx_buffered_bytes;
        unsigned long     col_16;
+       spinlock_t        lock;
 };
 
 /* Function prototypes */
@@ -429,8 +415,10 @@ static int     eth16i_open(struct net_device *dev);
 static int     eth16i_close(struct net_device *dev);
 static int     eth16i_tx(struct sk_buff *skb, struct net_device *dev);
 static void    eth16i_rx(struct net_device *dev);
+static void    eth16i_timeout(struct net_device *dev);
 static void    eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void    eth16i_reset(struct net_device *dev);
+static void    eth16i_timeout(struct net_device *dev);
 static void    eth16i_skip_packet(struct net_device *dev);
 static void    eth16i_multicast(struct net_device *dev); 
 static void    eth16i_select_regbank(unsigned char regbank, int ioaddr);
@@ -444,18 +432,10 @@ static int     eth16i_set_irq(struct net_device *dev);
 static ushort  eth16i_parse_mediatype(const char* s);
 #endif
 
-static struct enet_statistics *eth16i_get_stats(struct net_device *dev);
+static struct net_device_stats *eth16i_get_stats(struct net_device *dev);
 
 static char *cardname = "ICL EtherTeam 16i/32";
 
-#ifdef HAVE_DEVLIST 
-
-/* Support for alternate probe manager */
-/struct netdev_entry eth16i_drv = 
- {"eth16i", eth16i_probe1, ETH16I_IO_EXTENT, eth16i_probe_list}; 
-
-#else  /* Not HAVE_DEVLIST */
-
 int __init eth16i_probe(struct net_device *dev)
 {
        int i;
@@ -488,10 +468,11 @@ int __init eth16i_probe(struct net_device *dev)
 
        return ENODEV;
 }
-#endif  /* Not HAVE_DEVLIST */
 
 static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
 {
+       struct eth16i_local *lp;
+       
        static unsigned version_printed = 0;
        boot = 1;  /* To inform initilization that we are in boot probe */
 
@@ -535,17 +516,6 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
                printk(KERN_INFO "%s", version);
 
        dev->base_addr = ioaddr;
-       
-#if 0
-       if(dev->irq) {
-               if(eth16i_set_irq(dev)) {
-                       dev->irq = eth16i_get_irq(ioaddr);
-               }
-
-       }
-       else {
-#endif
-
        dev->irq = eth16i_get_irq(ioaddr);
 
        /* Try to obtain interrupt vector */
@@ -556,10 +526,6 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
                return -EAGAIN;
        }
 
-#if 0
-       irq2dev_map[dev->irq] = dev;
-#endif
-
        printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ",
               dev->name, cardname, ioaddr, dev->irq);
 
@@ -583,12 +549,16 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr)
        }
 
        memset(dev->priv, 0, sizeof(struct eth16i_local));
-
        dev->open               = eth16i_open;
        dev->stop               = eth16i_close;
        dev->hard_start_xmit    = eth16i_tx;
        dev->get_stats          = eth16i_get_stats;
-       dev->set_multicast_list = &eth16i_multicast;
+       dev->set_multicast_list = eth16i_multicast;
+       dev->tx_timeout         = eth16i_timeout;
+       dev->watchdog_timeo     = TX_TIMEOUT;
+
+       lp = (struct eth16i_local *)dev->priv;
+       spin_lock_init(&lp->lock);
 
        /* Fill in the fields of the device structure with ethernet values. */
        ether_setup(dev);
@@ -1004,10 +974,7 @@ static int eth16i_open(struct net_device *dev)
        /* Turn on interrupts*/
        outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);  
 
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
-
+       netif_start_queue(dev);
        MOD_INC_USE_COUNT;
 
        return 0;
@@ -1023,9 +990,8 @@ static int eth16i_close(struct net_device *dev)
        /* Turn off interrupts*/
        outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);  
 
-       dev->start = 0;
-       dev->tbusy = 1;
-
+       netif_stop_queue(dev);
+       
        lp->open_time = 0;
 
        /* Disable transmit and receive */
@@ -1042,153 +1008,115 @@ static int eth16i_close(struct net_device *dev)
        return 0;
 }
 
-static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
+static void eth16i_timeout(struct net_device *dev)
 {
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
        int ioaddr = dev->base_addr;
-       int status = 0;
+       /* 
+          If we get here, some higher level has decided that 
+          we are broken. There should really be a "kick me" 
+          function call instead. 
+          */
 
-       if(dev->tbusy) {
-               
-               /* 
-                  If we get here, some higher level has decided that 
-                  we are broken. There should really be a "kick me" 
-                  function call instead. 
-                  */
-
-               int tickssofar = jiffies - dev->trans_start;
-               if(tickssofar < TX_TIMEOUT)  
-                       return 1;                     
-
-               outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
-
-               printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n", 
-                      dev->name,
-                      inw(ioaddr + TX_STATUS_REG), 
-                      (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? 
+       outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+       printk(KERN_WARNING "%s: transmit timed out with status %04x, %s ?\n", 
+              dev->name,
+       inw(ioaddr + TX_STATUS_REG),  (inb(ioaddr + TX_STATUS_REG) & TX_DONE) ? 
                       "IRQ conflict" : "network cable problem");
 
-               dev->trans_start = jiffies;
-
-               /* Let's dump all registers */
-               if(eth16i_debug > 0) { 
-                       printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
-                              dev->name, inb(ioaddr + 0), 
-                              inb(ioaddr + 1), inb(ioaddr + 2), 
-                              inb(ioaddr + 3), inb(ioaddr + 4), 
-                              inb(ioaddr + 5),
-                              inb(ioaddr + 6), inb(ioaddr + 7));
+       dev->trans_start = jiffies;
 
-                       printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
-                              dev->name, inb(ioaddr + TRANSMIT_START_REG),
-                              inb(ioaddr + COL_16_REG));
+       /* Let's dump all registers */
+       if(eth16i_debug > 0) { 
+               printk(KERN_DEBUG "%s: timeout: %02x %02x %02x %02x %02x %02x %02x %02x.\n",
+                      dev->name, inb(ioaddr + 0), 
+                      inb(ioaddr + 1), inb(ioaddr + 2), 
+                      inb(ioaddr + 3), inb(ioaddr + 4), 
+                      inb(ioaddr + 5),
+                      inb(ioaddr + 6), inb(ioaddr + 7));
 
+               printk(KERN_DEBUG "%s: transmit start reg: %02x. collision reg %02x\n",
+                      dev->name, inb(ioaddr + TRANSMIT_START_REG),
+                      inb(ioaddr + COL_16_REG));
                        printk(KERN_DEBUG "lp->tx_queue = %d\n", lp->tx_queue);
-                       printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
-                       printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
-
-               }
-
-               lp->stats.tx_errors++;
-
-               eth16i_reset(dev);
-
-               dev->trans_start = jiffies;
-
-               outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-
+               printk(KERN_DEBUG "lp->tx_queue_len = %d\n", lp->tx_queue_len);
+               printk(KERN_DEBUG "lp->tx_started = %d\n", lp->tx_started);
        }
+       lp->stats.tx_errors++;
+       eth16i_reset(dev);
+       dev->trans_start = jiffies;
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+       netif_wake_queue(dev);
+}
 
-       /* 
-          If some higher layer thinks we've missed an tx-done interrupt
-          we are passed NULL. Caution: dev_tint() handles the cli()/sti()
-          itself 
-          */
-       
-       if(skb == NULL) {
-#if LINUX_VERSION_CODE < 0x020100
-               dev_tint(dev);
-#endif
-               if(eth16i_debug > 0) 
-                       printk(KERN_WARNING "%s: Missed tx-done interrupt.\n", dev->name);
-               return 0;
-       }
+static int eth16i_tx(struct sk_buff *skb, struct net_device *dev)
+{
+       struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
+       int ioaddr = dev->base_addr;
+       int status = 0;
+       ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+       unsigned char *buf = skb->data;
+       unsigned long flags;
 
-       /* Block a timer based transmitter from overlapping. 
-          This could better be done with atomic_swap(1, dev->tbusy), 
-          but set_bit() works as well. */
 
-       set_bit(0, (void *)&lp->tx_buf_busy);
-       
+       netif_stop_queue(dev);
+               
        /* Turn off TX interrupts */
        outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
+       
+       /* We would be better doing the disable_irq tricks the 3c509 does,
+          that would make this suck a lot less */
+          
+       spin_lock_irqsave(&lp->lock, flags);
 
-       if(test_and_set_bit(0, (void *)&dev->tbusy) != 0) {
-               printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
-               status = -1;
-       }
+       if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
+               if(eth16i_debug > 0) 
+                       printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);  
+       } 
        else {
-               ushort length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-               unsigned char *buf = skb->data;
+               outw(length, ioaddr + DATAPORT);
 
-               if( (length + 2) > (lp->tx_buf_size - lp->tx_queue_len)) {
-                       if(eth16i_debug > 0) 
-                               printk(KERN_WARNING "%s: Transmit buffer full.\n", dev->name);  
-               } 
+               if( ioaddr < 0x1000 ) 
+                       outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
                else {
-                       outw(length, ioaddr + DATAPORT);
-
-                       if( ioaddr < 0x1000 ) 
-                               outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-                       else {
-                               unsigned char frag = length % 4;
-
-                               outsl(ioaddr + DATAPORT, buf, length >> 2);
-
-                               if( frag != 0 ) {
-                                       outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
-                                       if( frag == 3 ) 
-                                               outsw(ioaddr + DATAPORT, 
-                                                     (buf + (length & 0xFFFC) + 2), 1);
-                               }
+                       unsigned char frag = length % 4;
+                       outsl(ioaddr + DATAPORT, buf, length >> 2);
+                       if( frag != 0 ) {
+                               outsw(ioaddr + DATAPORT, (buf + (length & 0xFFFC)), 1);
+                               if( frag == 3 ) 
+                                       outsw(ioaddr + DATAPORT, 
+                                             (buf + (length & 0xFFFC) + 2), 1);
                        }
-
-                       lp->tx_buffered_packets++;
-                       lp->tx_buffered_bytes = length;
-                       lp->tx_queue++;
-                       lp->tx_queue_len += length + 2;
-               }
-               
-               lp->tx_buf_busy = 0;
-
-               if(lp->tx_started == 0) {
-                       /* If the transmitter is idle..always trigger a transmit */
-                       outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
-                       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 < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
-                       /* There is still more room for one more packet in tx buffer */
-                       dev->tbusy = 0;
                }
-               
-               outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
-               
-               /* Turn TX interrupts back on */
-               /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
-               status = 0;
-       } 
+               lp->tx_buffered_packets++;
+               lp->tx_buffered_bytes = length;
+               lp->tx_queue++;
+               lp->tx_queue_len += length + 2;
+       }
+       lp->tx_buf_busy = 0;
 
-#if LINUX_VERSION_CODE >= 0x020100
+       if(lp->tx_started == 0) {
+               /* If the transmitter is idle..always trigger a transmit */
+               outb(TX_START | lp->tx_queue, ioaddr + TRANSMIT_START_REG);
+               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 < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
+               /* There is still more room for one more packet in tx buffer */
+               netif_wake_queue(dev);
+       }
+               
+       spin_unlock_irqrestore(&lp->lock, flags);
+       
+       outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
+       /* Turn TX interrupts back on */
+       /* outb(TX_INTR_DONE | TX_INTR_16_COL, ioaddr + TX_INTR_REG); */
+       status = 0;
        dev_kfree_skb(skb);
-#else
-       dev_kfree_skb(skb, FREE_WRITE);
-#endif
-
-       return status;
+       return 0;
 }
 
 static void eth16i_rx(struct net_device *dev)
@@ -1284,51 +1212,23 @@ static void eth16i_rx(struct net_device *dev)
                        break;
 
        } /* while */
-
-#if 0
-       {
-               int i;
-
-               for(i = 0; i < 20; i++) {
-                       if( (inb(ioaddr+RECEIVE_MODE_REG) & RX_BUFFER_EMPTY) == 
-                           RX_BUFFER_EMPTY)
-                               break;
-                       inw(ioaddr + DATAPORT);
-                       outb(SKIP_RX_PACKET, ioaddr + FILTER_SELF_RX_REG);
-               }
-
-               if(eth16i_debug > 1)
-                       printk(KERN_DEBUG "%s: Flushed receive buffer.\n", dev->name);
-       }
-#endif
-
-       return;
 }
 
 static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct net_device *dev = dev_id;
        struct eth16i_local *lp;
-       int ioaddr = 0,
-               status;
+       int ioaddr = 0, status;
 
-       if(dev == NULL) {
-               printk(KERN_WARNING "eth16i_interrupt(): irq %d for unknown device. \n", irq);
-               return;
-       }
+       ioaddr = dev->base_addr;
+       lp = (struct eth16i_local *)dev->priv;
 
        /* Turn off all interrupts from adapter */
        outw(ETH16I_INTR_OFF, ioaddr + TX_INTR_REG);
 
-       set_bit(0, (void *)&dev->tbusy);        /* Set the device busy so that */
        /* eth16i_tx wont be called */
+       spin_lock(&lp->lock);
 
-       if(dev->interrupt)
-               printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
-       dev->interrupt = 1;
-
-       ioaddr = dev->base_addr;
-       lp = (struct eth16i_local *)dev->priv;
        status = inw(ioaddr + TX_STATUS_REG);      /* Get the status */
        outw(status, ioaddr + TX_STATUS_REG);      /* Clear status bits */
 
@@ -1386,13 +1286,11 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                lp->tx_queue = 0;
                                lp->tx_queue_len = 0;
                                lp->tx_started = 1;
-                               dev->trans_start = jiffies;
-                               mark_bh(NET_BH); 
                        }
                        else {
                                lp->tx_started = 0;
-                               mark_bh(NET_BH);
                        }
+                       netif_wake_queue(dev);
                }
        }
 
@@ -1401,16 +1299,16 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                eth16i_rx(dev);  /* We have packet in receive buffer */
        }  
        
-       dev->interrupt = 0;
-       
        /* Turn interrupts back on */
        outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG);
        
        if(lp->tx_queue_len < lp->tx_buf_size - (ETH_FRAME_LEN + 2)) {
                /* There is still more room for one more packet in tx buffer */
-               dev->tbusy = 0;
+               netif_wake_queue(dev);
        }
        
+       spin_unlock(&lp->lock);
+       
        return;
 }
 
@@ -1442,10 +1340,6 @@ static void eth16i_reset(struct net_device *dev)
        lp->tx_buf_busy = 0;
        lp->tx_queue = 0;
        lp->tx_queue_len = 0;    
-
-       dev->interrupt = 0;
-       dev->start = 1;
-       dev->tbusy = 0;
        BITCLR(ioaddr + CONFIG_REG_0, DLC_EN);
 }
 
@@ -1462,10 +1356,9 @@ static void eth16i_multicast(struct net_device *dev)
        }
 }
 
-static struct enet_statistics *eth16i_get_stats(struct net_device *dev)
+static struct net_device_stats *eth16i_get_stats(struct net_device *dev)
 {
        struct eth16i_local *lp = (struct eth16i_local *)dev->priv;
-
        return &lp->stats;
 }
 
index eecbb9a56c27ed358b1a7c5e7ff8d7a3a04d6ad5..efed9b8171d7fac89f914b7f04dd0a012b74b4ee 100644 (file)
@@ -303,6 +303,7 @@ static int ewrk3_hw_init(struct net_device *dev, u_long iobase);
 static void ewrk3_init(struct net_device *dev);
 static int ewrk3_rx(struct net_device *dev);
 static int ewrk3_tx(struct net_device *dev);
+static void ewrk3_timeout(struct net_device *dev);
 
 static void EthwrkSignature(char *name, char *eeprom_image);
 static int DevicePresent(u_long iobase);
@@ -601,12 +602,14 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
                                printk(version);
                        }
                        /* The EWRK3-specific entries in the device structure. */
-                       dev->open = &ewrk3_open;
-                       dev->hard_start_xmit = &ewrk3_queue_pkt;
-                       dev->stop = &ewrk3_close;
-                       dev->get_stats = &ewrk3_get_stats;
-                       dev->set_multicast_list = &set_multicast_list;
-                       dev->do_ioctl = &ewrk3_ioctl;
+                       dev->open = ewrk3_open;
+                       dev->hard_start_xmit = ewrk3_queue_pkt;
+                       dev->stop = ewrk3_close;
+                       dev->get_stats = ewrk3_get_stats;
+                       dev->set_multicast_list = set_multicast_list;
+                       dev->do_ioctl = ewrk3_ioctl;
+                       dev->tx_timeout = ewrk3_timeout;
+                       dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
 
                        dev->mem_start = 0;
 
@@ -616,7 +619,6 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
        } else {
                status = -ENXIO;
        }
-
        return status;
 }
 \f
@@ -664,10 +666,7 @@ static int ewrk3_open(struct net_device *dev)
                                printk("  cmr:  0x%02x\n", inb(EWRK3_CMR));
                                printk("  fmqc: 0x%02x\n", inb(EWRK3_FMQC));
                        }
-                       dev->tbusy = 0;
-                       dev->start = 1;
-                       dev->interrupt = UNMASK_INTERRUPTS;
-
+                       netif_start_queue(dev);
                        /*
                           ** Unmask EWRK3 board interrupts
                         */
@@ -676,10 +675,9 @@ static int ewrk3_open(struct net_device *dev)
 
                }
        } else {
-               dev->start = 0;
-               dev->tbusy = 1;
-               printk("%s: ewrk3 available for hard strapped set up only.\n", dev->name);
-               printk("      Run the 'ewrk3setup' utility or remove the hard straps.\n");
+               printk(KERN_ERR "%s: ewrk3 available for hard strapped set up only.\n", dev->name);
+               printk(KERN_ERR "      Run the 'ewrk3setup' utility or remove the hard straps.\n");
+               return -EINVAL;
        }
 
        MOD_INC_USE_COUNT;
@@ -722,149 +720,148 @@ static void ewrk3_init(struct net_device *dev)
 }
 
 /*
-   ** Writes a socket buffer to the free page queue
+ *  Transmit timeout
  */
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev)
+static void ewrk3_timeout(struct net_device *dev)
 {
        struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
-       u_long iobase = dev->base_addr;
-       int status = 0;
        u_char icr, csr;
+       u_long iobase = dev->base_addr;
+       
+       if (!lp->hard_strapped) 
+       {
+               printk(KERN_WARNING"%s: transmit timed/locked out, status %04x, resetting.\n",
+                      dev->name, inb(EWRK3_CSR));
 
-       /* Transmitter timeout, serious problems. */
-       if (dev->tbusy || lp->lock) {
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < QUEUE_PKT_TIMEOUT) {
-                       status = -1;
-               } else if (!lp->hard_strapped) {
-                       printk("%s: transmit timed/locked out, status %04x, resetting.\n",
-                              dev->name, inb(EWRK3_CSR));
-
-                       /*
-                          ** Mask all board interrupts
-                        */
-                       DISABLE_IRQs;
-
-                       /*
-                          ** Stop the TX and RX...
-                        */
-                       STOP_EWRK3;
-
-                       ewrk3_init(dev);
-
-                       /*
-                          ** Unmask EWRK3 board interrupts
-                        */
-                       ENABLE_IRQs;
-
-                       dev->tbusy = 0;
-                       dev->trans_start = jiffies;
-               }
-       } else if (skb->len > 0) {
+               /*
+                  ** Mask all board interrupts
+                */
+               DISABLE_IRQs;
 
                /*
-                  ** Block a timer-based transmit from overlapping.  This could better be
-                  ** done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+                  ** Stop the TX and RX...
                 */
-               if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
-                       printk("%s: Transmitter access conflict.\n", dev->name);
+               STOP_EWRK3;
 
-               DISABLE_IRQs;   /* So that the page # remains correct */
+               ewrk3_init(dev);
 
                /*
-                  ** Get a free page from the FMQ when resources are available
+                  ** Unmask EWRK3 board interrupts
                 */
-               if (inb(EWRK3_FMQC) > 0) {
-                       u_long buf = 0;
-                       u_char page;
+               ENABLE_IRQs;
 
-                       if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
-                               /*
-                                  ** Set up shared memory window and pointer into the window
-                                */
-                               while (test_and_set_bit(0, (void *) &lp->lock) != 0);   /* Wait for lock to free */
-                               if (lp->shmem_length == IO_ONLY) {
-                                       outb(page, EWRK3_IOPR);
-                               } else if (lp->shmem_length == SHMEM_2K) {
-                                       buf = lp->shmem_base;
-                                       outb(page, EWRK3_MPR);
-                               } else if (lp->shmem_length == SHMEM_32K) {
-                                       buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
-                                       outb((page >> 4), EWRK3_MPR);
-                               } else if (lp->shmem_length == SHMEM_64K) {
-                                       buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
-                                       outb((page >> 5), EWRK3_MPR);
-                               } else {
-                                       status = -1;
-                                       printk("%s: Oops - your private data area is hosed!\n", dev->name);
-                               }
+               dev->trans_start = jiffies;
+               netif_wake_queue(dev);
+       }
+}
 
-                               if (!status) {
+/*
+   ** Writes a socket buffer to the free page queue
+ */
+static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_device *dev)
+{
+       struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
+       u_long iobase = dev->base_addr;
+       int status = 0;
+       u_char icr;
 
-                                       /*
-                                          ** Set up the buffer control structures and copy the data from
-                                          ** the socket buffer to the shared memory .
-                                        */
+       netif_stop_queue(dev);
+#ifdef CONFIG_SMP
+#error "This needs spinlocks"
+#endif
+       DISABLE_IRQs;   /* So that the page # remains correct */
 
-                                       if (lp->shmem_length == IO_ONLY) {
-                                               int i;
-                                               u_char *p = skb->data;
+       /*
+          ** Get a free page from the FMQ when resources are available
+        */
+       if (inb(EWRK3_FMQC) > 0) 
+       {
+               u_long buf = 0;
+               u_char page;
 
+               if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
+                       /*
+                          ** Set up shared memory window and pointer into the window
+                        */
+                       while (test_and_set_bit(0, (void *) &lp->lock) != 0);   /* Wait for lock to free */
+                       if (lp->shmem_length == IO_ONLY) {
+                               outb(page, EWRK3_IOPR);
+                       } else if (lp->shmem_length == SHMEM_2K) {
+                               buf = lp->shmem_base;
+                               outb(page, EWRK3_MPR);
+                       } else if (lp->shmem_length == SHMEM_32K) {
+                               buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+                               outb((page >> 4), EWRK3_MPR);
+                       } else if (lp->shmem_length == SHMEM_64K) {
+                               buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+                               outb((page >> 5), EWRK3_MPR);
+                       } else {
+                               status = -1;
+                               printk(KERN_ERR "%s: Oops - your private data area is hosed!\n", dev->name);
+                       }
+
+                       if (!status) {
+                               /*
+                                  ** Set up the buffer control structures and copy the data from
+                                  ** the socket buffer to the shared memory .
+                                */
+                                       if (lp->shmem_length == IO_ONLY) {
+                                       int i;
+                                       u_char *p = skb->data;
                                                outb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);
-                                               outb((char) (skb->len & 0xff), EWRK3_DATA);
-                                               outb((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
-                                               outb((char) 0x04, EWRK3_DATA);
-                                               for (i = 0; i < skb->len; i++) {
-                                                       outb(*p++, EWRK3_DATA);
-                                               }
+                                       outb((char) (skb->len & 0xff), EWRK3_DATA);
+                                       outb((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
+                                       outb((char) 0x04, EWRK3_DATA);
+                                       for (i = 0; i < skb->len; i++) {
+                                               outb(*p++, EWRK3_DATA);
+                                       }
+                                       outb(page, EWRK3_TQ);   /* Start sending pkt */
+                               } else {
+                                       writeb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), (char *) buf);   /* ctrl byte */
+                                       buf += 1;
+                                       writeb((char) (skb->len & 0xff), (char *) buf);         /* length (16 bit xfer) */
+                                       buf += 1;
+                                       if (lp->txc) {
+                                               writeb((char) (((skb->len >> 8) & 0xff) | XCT), (char *) buf);
+                                               buf += 1;
+                                               writeb(0x04, (char *) buf);     /* index byte */
+                                               buf += 1;
+                                               writeb(0x00, (char *) (buf + skb->len));        /* Write the XCT flag */
+                                               isa_memcpy_toio(buf, skb->data, PRELOAD);       /* Write PRELOAD bytes */
                                                outb(page, EWRK3_TQ);   /* Start sending pkt */
+                                               isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
+                                               writeb(0xff, (char *) (buf + skb->len));        /* Write the XCT flag */
                                        } else {
-                                               writeb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), (char *) buf);   /* ctrl byte */
+                                               writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
                                                buf += 1;
-                                               writeb((char) (skb->len & 0xff), (char *) buf);         /* length (16 bit xfer) */
+                                               writeb(0x04, (char *) buf);     /* index byte */
                                                buf += 1;
-                                               if (lp->txc) {
-                                                       writeb((char) (((skb->len >> 8) & 0xff) | XCT), (char *) buf);
-                                                       buf += 1;
-                                                       writeb(0x04, (char *) buf);     /* index byte */
-                                                       buf += 1;
-                                                       writeb(0x00, (char *) (buf + skb->len));        /* Write the XCT flag */
-                                                       isa_memcpy_toio(buf, skb->data, PRELOAD);       /* Write PRELOAD bytes */
-                                                       outb(page, EWRK3_TQ);   /* Start sending pkt */
-                                                       isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
-                                                       writeb(0xff, (char *) (buf + skb->len));        /* Write the XCT flag */
-                                               } else {
-                                                       writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
-                                                       buf += 1;
-                                                       writeb(0x04, (char *) buf);     /* index byte */
-                                                       buf += 1;
-                                                       isa_memcpy_toio(buf, skb->data, skb->len);              /* Write data bytes */
-                                                       outb(page, EWRK3_TQ);   /* Start sending pkt */
-                                               }
+                                               isa_memcpy_toio(buf, skb->data, skb->len);              /* Write data bytes */
+                                               outb(page, EWRK3_TQ);   /* Start sending pkt */
                                        }
-
-                                       dev->trans_start = jiffies;
-                                       dev_kfree_skb(skb);
-
-                               } else {        /* return unused page to the free memory queue */
-                                       outb(page, EWRK3_FMQ);
                                }
-                               lp->lock = 0;   /* unlock the page register */
-                       } else {
-                               printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
-                                      (u_char) page);
+
+                               dev->trans_start = jiffies;
+                               dev_kfree_skb(skb);
+                       } else {        /* return unused page to the free memory queue */
+                               outb(page, EWRK3_FMQ);
                        }
+                       lp->lock = 0;   /* unlock the page register */
                } else {
-                       printk("ewrk3_queue_pkt(): No free resources...\n");
-                       printk("ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
+                       printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
+                              (u_char) page);
                }
+       } else {
+               printk(KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n", dev->name);
+               printk(KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", dev->name, inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
+       }
 
-               /* Check for free resources: clear 'tbusy' if there are some */
-               if (inb(EWRK3_FMQC) > 0) {
-                       dev->tbusy = 0;
-               }
-               ENABLE_IRQs;
+       /* Check for free resources: clear 'tbusy' if there are some */
+       if (inb(EWRK3_FMQC) > 0) {
+               netif_wake_queue(dev);
        }
+       ENABLE_IRQs;
        return status;
 }
 
@@ -878,60 +875,46 @@ static void ewrk3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        u_long iobase;
        u_char icr, cr, csr;
 
-       if (dev == NULL) {
-               printk("ewrk3_interrupt(): irq %d for unknown device.\n", irq);
-       } else {
-               lp = (struct ewrk3_private *) dev->priv;
-               iobase = dev->base_addr;
-
-               if (dev->interrupt)
-                       printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
-               dev->interrupt = MASK_INTERRUPTS;
+       lp = (struct ewrk3_private *) dev->priv;
+       iobase = dev->base_addr;
 
-               /* get the interrupt information */
-               csr = inb(EWRK3_CSR);
-
-               /*
-                  ** Mask the EWRK3 board interrupts and turn on the LED
-                */
-               DISABLE_IRQs;
-
-               cr = inb(EWRK3_CR);
-               cr |= CR_LED;
-               outb(cr, EWRK3_CR);
+       /* get the interrupt information */
+       csr = inb(EWRK3_CSR);
 
-               if (csr & CSR_RNE)      /* Rx interrupt (packet[s] arrived) */
-                       ewrk3_rx(dev);
+       /*
+        ** Mask the EWRK3 board interrupts and turn on the LED
+        */
+       DISABLE_IRQs;
 
-               if (csr & CSR_TNE)      /* Tx interrupt (packet sent) */
-                       ewrk3_tx(dev);
+       cr = inb(EWRK3_CR);
+       cr |= CR_LED;
+       outb(cr, EWRK3_CR);
 
-               /*
-                  ** Now deal with the TX/RX disable flags. These are set when there
-                  ** are no more resources. If resources free up then enable these
-                  ** interrupts, otherwise mask them - failure to do this will result
-                  ** in the system hanging in an interrupt loop.
-                */
-               if (inb(EWRK3_FMQC)) {  /* any resources available? */
-                       lp->irq_mask |= ICR_TXDM | ICR_RXDM;    /* enable the interrupt source */
-                       csr &= ~(CSR_TXD | CSR_RXD);    /* ensure restart of a stalled TX or RX */
-                       outb(csr, EWRK3_CSR);
-                       dev->tbusy = 0;         /* clear TX busy flag */
-                       mark_bh(NET_BH);
-               } else {
-                       lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM);         /* disable the interrupt source */
-               }
+       if (csr & CSR_RNE)      /* Rx interrupt (packet[s] arrived) */
+               ewrk3_rx(dev);
 
-               /* Unmask the EWRK3 board interrupts and turn off the LED */
-               cr &= ~CR_LED;
-               outb(cr, EWRK3_CR);
+       if (csr & CSR_TNE)      /* Tx interrupt (packet sent) */
+               ewrk3_tx(dev);
 
-               dev->interrupt = UNMASK_INTERRUPTS;
-               ENABLE_IRQs;
+       /*
+        ** Now deal with the TX/RX disable flags. These are set when there
+        ** are no more resources. If resources free up then enable these
+        ** interrupts, otherwise mask them - failure to do this will result
+        ** in the system hanging in an interrupt loop.
+        */
+       if (inb(EWRK3_FMQC)) {  /* any resources available? */
+               lp->irq_mask |= ICR_TXDM | ICR_RXDM;    /* enable the interrupt source */
+               csr &= ~(CSR_TXD | CSR_RXD);    /* ensure restart of a stalled TX or RX */
+               outb(csr, EWRK3_CSR);
+               netif_wake_queue(dev);
+       } else {
+               lp->irq_mask &= ~(ICR_TXDM | ICR_RXDM);         /* disable the interrupt source */
        }
 
-       return;
+       /* Unmask the EWRK3 board interrupts and turn off the LED */
+       cr &= ~CR_LED;
+       outb(cr, EWRK3_CR);
+       ENABLE_IRQs;
 }
 
 static int ewrk3_rx(struct net_device *dev)
@@ -1120,9 +1103,8 @@ static int ewrk3_close(struct net_device *dev)
        u_long iobase = dev->base_addr;
        u_char icr, csr;
 
-       dev->start = 0;
-       dev->tbusy = 1;
-
+       netif_stop_queue(dev);
+       
        if (ewrk3_debug > 1) {
                printk("%s: Shutting down ethercard, status was %2.2x.\n",
                       dev->name, inb(EWRK3_CSR));
@@ -1369,8 +1351,7 @@ static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
    ** are not available then insert a new device structure at the end of
    ** the current list.
  */
-static struct net_device * __init 
-alloc_device(struct net_device *dev, u_long iobase)
+static struct net_device * __init  alloc_device(struct net_device *dev, u_long iobase)
 {
        struct net_device *adev = NULL;
        int fixed = 0, new_dev = 0;
index c1c9fde27587802857fc216fa18489b29be5d0c7..785a3fafdf18b71bc4d358de87d57f2a0a828dbf 100644 (file)
@@ -919,7 +919,8 @@ u_int tag;
                                /* An IP frame was transmitted to a Bad AL_PA. Free up
                                 * the skb used.
                                 */
-                               dev_kfree_skb((struct sk_buff *)(bus_to_virt(transaction_id)));
+                               dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
+                               netif_wake_queue(fi->dev);
                        }
                } /* End of IP frame timing out. */
        } /* End of frame timing out. */
@@ -977,7 +978,8 @@ u_int tag;
                         * Free the skb that was used for this IP frame.
                         */
                        if ((status == 0) && (seq_count > 1)) {
-                               dev_kfree_skb((struct sk_buff *)(bus_to_virt(transaction_id)));
+                               dev_kfree_skb_irq((struct sk_buff *)(bus_to_virt(transaction_id)));
+                               netif_wake_queue(fi->dev);
                        }
                }
        }
@@ -2914,65 +2916,59 @@ static void update_EDB_indx(struct fc_info *fi)
 
 static int iph5526_open(struct net_device *dev)
 {
-       dev->tbusy = 0;
-       dev->interrupt = 0;
-       dev->start = 1;
+       netif_start_queue(dev);
        MOD_INC_USE_COUNT;
        return 0;
 }
 
 static int iph5526_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
+       netif_stop_queue(dev);
        MOD_DEC_USE_COUNT;
        return 0;
 }
 
+static void iph5526_timeout(struct net_device *dev)
+{
+       struct fc_info *fi = (struct fc_info*)dev->priv;
+       printk(KERN_WARNING "%s: timed out on send.\n", dev->name);
+       fi->fc_stats.rx_dropped++;
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
+
 static int iph5526_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-struct fc_info *fi = (struct fc_info*)dev->priv;
-int status = 0;
-short type = 0;
-u_long flags;
+       struct fc_info *fi = (struct fc_info*)dev->priv;
+       int status = 0;
+       short type = 0;
+       u_long flags;
+       struct fcllc *fcllc;
+       
        ENTER("iph5526_send_packet");
-       if (dev->tbusy) {
-               printk(KERN_WARNING "%s: DEVICE BUSY\n", dev->name);
-               dev->tbusy = 0;
-               fi->fc_stats.rx_dropped++;
-               dev->trans_start = jiffies;
-               return 0;
-       }
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-               printk(KERN_WARNING "%s: Transmitter access conflict.\n", 
-dev->name);
-               fi->fc_stats.rx_dropped++;
-               return 1;
-       }
-       else {
-               struct fcllc *fcllc;
-               /* Strip off the pseudo header.
-                */
-               skb->data = skb->data + 2*FC_ALEN; 
-               skb->len = skb->len - 2*FC_ALEN;
-               fcllc = (struct fcllc *)skb->data;
-               type = ntohs(fcllc->ethertype);
-
-               spin_lock_irqsave(&fi->fc_lock, flags);
-               switch(type) {
-                       case ETH_P_IP:
-                               status = tx_ip_packet(skb, skb->len, fi);
-                               break;
-                       case ETH_P_ARP:
-                               status = tx_arp_packet(skb->data, skb->len, fi);
-                               break;
-                       default:
-                               T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
-                               fi->fc_stats.rx_dropped++;
-                               break;
-               }
-               spin_unlock_irqrestore(&fi->fc_lock, flags);
+       
+       netif_stop_queue(dev);
+       /* Strip off the pseudo header.
+        */
+       skb->data = skb->data + 2*FC_ALEN; 
+       skb->len = skb->len - 2*FC_ALEN;
+       fcllc = (struct fcllc *)skb->data;
+       type = ntohs(fcllc->ethertype);
+
+       spin_lock_irqsave(&fi->fc_lock, flags);
+       switch(type) {
+               case ETH_P_IP:
+                       status = tx_ip_packet(skb, skb->len, fi);
+                       break;
+               case ETH_P_ARP:
+                       status = tx_arp_packet(skb->data, skb->len, fi);
+                       break;
+               default:
+                       T_MSG("WARNING!!! Received Unknown Packet Type... Discarding...");
+                       fi->fc_stats.rx_dropped++;
+                       break;
        }
+       spin_unlock_irqrestore(&fi->fc_lock, flags);
 
        if (status) {
                fi->fc_stats.tx_bytes += skb->len;
@@ -2981,14 +2977,14 @@ dev->name);
        else
                fi->fc_stats.rx_dropped++;
        dev->trans_start = jiffies;
-       dev->tbusy = 0;
        /* We free up the IP buffers in the OCI_interrupt handler.
         * status == 0 implies that the frame was not transmitted. So the
         * skb is freed here.
         */
        if ((type == ETH_P_ARP) || (status == 0))
                dev_kfree_skb(skb);
-       mark_bh(NET_BH);
+       else
+               netif_wake_queue(dev);
        LEAVE("iph5526_send_packet");
        return 0;
 }
index af2db03bcf1c5273307ca60190c0ba83b3269b38..b26351886ccea5a4e4ddaadbc36a45d7e5729f1a 100644 (file)
@@ -58,8 +58,9 @@ static const char *version =
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 
-static int fmv18x_probe_list[] __initdata =
-{0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0};
+static int fmv18x_probe_list[] __initdata = {
+       0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
+};
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
@@ -127,14 +128,8 @@ static void set_multicast_list(struct net_device *dev);
    If dev->base_addr == 2, allocate space for the device and return success
    (detachable devices only).
    */
-#ifdef HAVE_DEVLIST
-/* Support for an alternate probe manager, which will eliminate the
-   boilerplate below. */
-struct netdev_entry fmv18x_drv =
-{"fmv18x", fmv18x_probe1, FMV18X_IO_EXTENT, fmv18x_probe_list};
-#else
-int __init 
-fmv18x_probe(struct net_device *dev)
+
+int __init fmv18x_probe(struct net_device *dev)
 {
        int i;
        int base_addr = dev ? dev->base_addr : 0;
@@ -154,7 +149,6 @@ fmv18x_probe(struct net_device *dev)
 
        return ENODEV;
 }
-#endif
 
 /* The Fujitsu datasheet suggests that the NIC be probed for by checking its
    "signature", the default bit pattern after a reset.  This *doesn't* work --
@@ -584,11 +578,6 @@ static int net_close(struct net_device *dev)
 static struct net_device_stats *net_get_stats(struct net_device *dev)
 {
        struct net_local *lp = (struct net_local *)dev->priv;
-
-       cli();
-       /* ToDo: Update the statistics from the device registers. */
-       sti();
-
        return &lp->stats;
 }
 
index 55ed5254e876d67b97352171413c824139a61fb0..689dcdb3634d5b4af9e529cbc060d4ecb8206d60 100644 (file)
@@ -222,7 +222,7 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
 
        dev = bpq_get_ax25_dev(dev);
 
-       if (dev == NULL || dev->start == 0) {
+       if (dev == NULL || test_bit(LINK_STATE_START, &dev->state) == 0) {
                kfree_skb(skb);
                return 0;
        }
@@ -275,7 +275,7 @@ static int bpq_xmit(struct sk_buff *skb, struct net_device *dev)
         * Just to be *really* sure not to send anything if the interface
         * is down, the ethernet device may have gone.
         */
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                bpq_check_devices(dev);
                kfree_skb(skb);
                return -ENODEV;
@@ -407,22 +407,15 @@ static int bpq_open(struct net_device *dev)
 {
        if (bpq_check_devices(dev))
                return -ENODEV;         /* oops, it's gone */
-
-       dev->tbusy = 0;
-       dev->start = 1;
-
        MOD_INC_USE_COUNT;
-
+       netif_start_queue(dev);
        return 0;
 }
 
 static int bpq_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
        MOD_DEC_USE_COUNT;
-
        return 0;
 }
 
index afba5cb147788efcdbadccca3acd866db71cee08..c5ae0d0892c8bdc068ac197e7dea8b71ddb406cb 100644 (file)
@@ -643,7 +643,6 @@ static int scc_open(struct net_device *dev)
   }
 
   /* Initialize local variables */
-  dev->tbusy = 0;
   priv->rx_ptr = 0;
   priv->rx_over = 0;
   priv->rx_head = priv->rx_tail = priv->rx_count = 0;
@@ -732,7 +731,7 @@ static int scc_open(struct net_device *dev)
   /* Configure PI2 DMA */
   if (info->type <= TYPE_PI2) outb_p(1, io + PI_DREQ_MASK);
 
-  dev->start = 1;
+  netif_start_queue(dev);
   info->open++;
   MOD_INC_USE_COUNT;
 
@@ -747,9 +746,8 @@ static int scc_close(struct net_device *dev)
   int io = dev->base_addr;
   int cmd = priv->cmd;
 
-  dev->start = 0;
+  netif_stop_queue(dev);
   info->open--;
-  MOD_DEC_USE_COUNT;
 
   if (info->type == TYPE_TWIN)
     /* Drop DTR */
@@ -768,6 +766,7 @@ static int scc_close(struct net_device *dev)
     if (info->type <= TYPE_PI2) outb_p(0, io + PI_DREQ_MASK);
     free_irq(dev->irq, info);
   }
+  MOD_DEC_USE_COUNT;
   return 0;
 }
 
@@ -779,16 +778,16 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
   
   switch (cmd) {
   case SIOCGSCCPARAM:
-    rc = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct scc_param));
-    if (rc) return rc;
-    copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param));
+    if(copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
+       return -EFAULT;
     return 0;
   case SIOCSSCCPARAM:
-    if (!suser()) return -EPERM;
-    rc = verify_area(VERIFY_READ, ifr->ifr_data, sizeof(struct scc_param));
-    if (rc) return rc;
-    if (dev->start) return -EAGAIN;
-    copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param));
+    if (!capable(CAP_NET_ADMIN)) 
+       return -EPERM;
+    if (test_bit(LINK_STATE_START, &dev->state)) 
+       return -EAGAIN;
+    if(copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
+       return -EFAULT;
     dev->dma = priv->param.dma;
     return 0;
   default:
@@ -806,18 +805,8 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
   int i;
 
   /* Block a timer-based transmit from overlapping */
-  if (test_and_set_bit(0, (void *) &priv->tx_sem) != 0) {
-    atomic_inc((void *) &priv->stats.tx_dropped);
-    dev_kfree_skb(skb);
-    return 0;
-  }
-
-  /* Return with an error if we cannot accept more data */
-  if (dev->tbusy) {
-    priv->tx_sem = 0;
-    return -1;
-  }
-
+  netif_stop_queue(dev);
+  
   /* Transfer data to DMA buffer */
   i = priv->tx_head;
   memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
@@ -829,7 +818,8 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
   /* Set the busy flag if we just filled up the last buffer */
   priv->tx_head = (i + 1) % NUM_TX_BUF;
   priv->tx_count++;
-  if (priv->tx_count == NUM_TX_BUF) dev->tbusy = 1;
+  if (priv->tx_count != NUM_TX_BUF)
+       netif_wake_queue(dev);
 
   /* Set new TX state */
   if (priv->tx_state == TX_IDLE) {
@@ -1139,7 +1129,6 @@ static void es_isr(struct net_device *dev)
     /* Remove frame from FIFO */
     priv->tx_tail = (i + 1) % NUM_TX_BUF;
     priv->tx_count--;
-    dev->tbusy = 0;
     /* Check if another frame is available and we are allowed to transmit */
     if (priv->tx_count && (jiffies - priv->tx_start) < priv->param.txtime) {
       if (dev->dma) {
@@ -1171,7 +1160,7 @@ static void es_isr(struct net_device *dev)
       priv->stats.tx_packets++;
     }
     /* Inform upper layers */
-    mark_bh(NET_BH);
+    netif_wake_queue(dev);
   }
 
   /* DCD transition */
index 4de421874de14a6220cfa2e03139c811d58c877b..08d079b1d4d774c83f39297475b4a40d7f31804a 100644 (file)
@@ -317,12 +317,12 @@ static inline void scc_sti(int irq)
 
 static inline void scc_lock_dev(struct scc_channel *scc)
 {
-       scc->dev->tbusy = 1;
+       netif_stop_queue(scc->dev);
 }
 
 static inline void scc_unlock_dev(struct scc_channel *scc)
 {
-       scc->dev->tbusy = 0;
+       netif_wake_queue(scc->dev);
 }
 
 static inline void scc_discard_buffers(struct scc_channel *scc)
@@ -1660,9 +1660,7 @@ static int scc_net_open(struct net_device *dev)
  
        init_channel(scc);
 
-       dev->tbusy = 0;
-       dev->start = 1;
-
+       netif_start_queue(dev);
        return 0;
 }
 
@@ -1692,9 +1690,7 @@ static int scc_net_close(struct net_device *dev)
        
        scc_discard_buffers(scc);
 
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
        return 0;
 }
 
@@ -1727,7 +1723,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
        unsigned long flags;
        char kisscmd;
        
-       if (scc == NULL || scc->magic != SCC_MAGIC || dev->tbusy)
+       if (scc == NULL || scc->magic != SCC_MAGIC)
        {
                dev_kfree_skb(skb);
                return 0;
@@ -1753,7 +1749,7 @@ static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
                return 0;
        }
 
-       save_flags(flags);
+       save_flags(flags); 
        cli();
        
        if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len)
index e99d4c7a9c83202e92a1480a258e1072ad88e1f7..7d694fef7cbcf8094d784af62252a306078b99a7 100644 (file)
@@ -649,7 +649,7 @@ static void yam_dotimer(unsigned long dummy)
 
        for (i = 0; i < NR_PORTS; i++) {
                struct net_device *dev = &yam_ports[i].dev;
-               if (dev->start)
+               if (test_bit(LINK_STATE_START, &dev->state))
                        yam_arbitrate(dev);
        }
        yam_timer.expires = jiffies + HZ / 100;
@@ -748,7 +748,7 @@ static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                yp = &yam_ports[i];
                dev = &yp->dev;
 
-               if (!dev->start)
+               if (!test_bit(LINK_STATE_START, &dev->state))
                        continue;
 
                while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) {
@@ -794,7 +794,7 @@ static int yam_net_get_info(char *buffer, char **start, off_t offset, int length
                if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0)
                        continue;
                len += sprintf(buffer + len, "Device %s\n", yam_ports[i].name);
-               len += sprintf(buffer + len, "  Up       %d\n", yam_ports[i].dev.start);
+               len += sprintf(buffer + len, "  Up       %d\n", test_bit(LINK_STATE_START, &yam_ports[i].dev.state));
                len += sprintf(buffer + len, "  Speed    %u\n", yam_ports[i].bitrate);
                len += sprintf(buffer + len, "  IoBase   0x%x\n", yam_ports[i].iobase);
                len += sprintf(buffer + len, "  BaudRate %u\n", yam_ports[i].baudrate);
@@ -903,7 +903,9 @@ static int yam_open(struct net_device *dev)
        request_region(dev->base_addr, YAM_EXTENT, dev->name);
 
        yam_set_uart(dev);
-       dev->start = 1;
+
+       netif_start_queue(dev);
+       
        yp->slotcnt = yp->slot / 10;
 
        /* Reset overruns for all ports - FPGA programming makes overruns */
@@ -935,8 +937,7 @@ static int yam_close(struct net_device *dev)
        /* Remove IRQ handler if last */
        free_irq(dev->irq, NULL);
        release_region(dev->base_addr, YAM_EXTENT);
-       dev->start = 0;
-       dev->tbusy = 1;
+       netif_stop_queue(dev);
        while ((skb = skb_dequeue(&yp->send_queue)))
                dev_kfree_skb(skb);
 
@@ -973,7 +974,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                return -EINVAL;                 /* unused */
 
        case SIOCYAMSMCS:
-               if (dev->start)
+               if (test_bit(LINK_STATE_START, &dev->state))
                        return -EINVAL;         /* Cannot change this parameter when up */
                ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_ATOMIC);
                ym->bitrate = 9600;
@@ -989,13 +990,13 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                if (copy_from_user(&yi, ifr->ifr_data, sizeof(struct yamdrv_ioctl_cfg)))
                         return -EFAULT;
 
-               if ((yi.cfg.mask & YAM_IOBASE) && dev->start)
+               if ((yi.cfg.mask & YAM_IOBASE) && test_bit(LINK_STATE_START, &dev->state))
                        return -EINVAL;         /* Cannot change this parameter when up */
-               if ((yi.cfg.mask & YAM_IRQ) && dev->start)
+               if ((yi.cfg.mask & YAM_IRQ) && test_bit(LINK_STATE_START, &dev->state))
                        return -EINVAL;         /* Cannot change this parameter when up */
-               if ((yi.cfg.mask & YAM_BITRATE) && dev->start)
+               if ((yi.cfg.mask & YAM_BITRATE) && test_bit(LINK_STATE_START, &dev->state))
                        return -EINVAL;         /* Cannot change this parameter when up */
-               if ((yi.cfg.mask & YAM_BAUDRATE) && dev->start)
+               if ((yi.cfg.mask & YAM_BAUDRATE) && test_bit(LINK_STATE_START, &dev->state))
                        return -EINVAL;         /* Cannot change this parameter when up */
 
                if (yi.cfg.mask & YAM_IOBASE) {
@@ -1164,8 +1165,6 @@ int __init yam_init(void)
                dev->irq = yam_ports[i].irq;
                dev->init = yam_probe;
                dev->if_port = 0;
-               dev->start = 0;
-               dev->tbusy = 1;
 
                if (register_netdev(dev)) {
                        printk(KERN_WARNING "yam: cannot register net  device %s\n", dev->name);
@@ -1211,7 +1210,7 @@ void cleanup_module(void)
                struct net_device *dev = &yam_ports[i].dev;
                if (!dev->priv)
                        continue;
-               if (dev->start)
+               if (test_bit(LINK_STATE_START, &dev->state))
                        yam_close(dev);
                unregister_netdev(dev);
        }
index 5c671a4ea39df142bdde60ee55dcfa04ca64e43c..2e82ceca52d4d4b03e44a9cc771ea69ec45aebd2 100644 (file)
@@ -228,6 +228,7 @@ static int  ni65_open(struct net_device *dev);
 static int  ni65_lance_reinit(struct net_device *dev);
 static void ni65_init_lance(struct priv *p,unsigned char*,int,int);
 static int  ni65_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void  ni65_timeout(struct net_device *dev);
 static int  ni65_close(struct net_device *dev);
 static int  ni65_alloc_buffer(struct net_device *dev);
 static void ni65_free_buffer(struct priv *p);
@@ -278,16 +279,13 @@ static int ni65_open(struct net_device *dev)
 
        if(ni65_lance_reinit(dev))
        {
-               dev->tbusy     = 0;
-               dev->interrupt = 0;
-               dev->start     = 1;
+               netif_start_queue(dev);
                MOD_INC_USE_COUNT;
                return 0;
        }
        else
        {
                free_irq(dev->irq,dev);
-               dev->start = 0;
                return -EAGAIN;
        }
 }
@@ -299,6 +297,8 @@ static int ni65_close(struct net_device *dev)
 {
        struct priv *p = (struct priv *) dev->priv;
 
+       netif_stop_queue(dev);
+       
        outw(inw(PORT+L_RESET),PORT+L_RESET); /* that's the hard way */
 
 #ifdef XMT_VIA_SKB
@@ -314,8 +314,6 @@ static int ni65_close(struct net_device *dev)
        }
 #endif
        free_irq(dev->irq,dev);
-       dev->tbusy = 1;
-       dev->start = 0;
        MOD_DEC_USE_COUNT;
        return 0;
 }
@@ -482,15 +480,13 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr)
        dev->open               = ni65_open;
        dev->stop               = ni65_close;
        dev->hard_start_xmit    = ni65_send_packet;
+       dev->tx_timeout         = ni65_timeout;
+       dev->watchdog_timeo     = HZ/2;
        dev->get_stats          = ni65_get_stats;
        dev->set_multicast_list = set_multicast_list;
 
        ether_setup(dev);
 
-       dev->interrupt          = 0;
-       dev->tbusy              = 0;
-       dev->start              = 0;
-
        return 0; /* everything is OK */
 }
 
@@ -714,7 +710,8 @@ static void ni65_stop_start(struct net_device *dev,struct priv *p)
                }
                p->rmdnum = p->tmdlast = 0;
                if(!p->lock)
-                       dev->tbusy = (p->tmdnum || !p->xmit_queued) ? 0 : 1;
+                       if (p->tmdnum || !p->xmit_queued)
+                               netif_wake_queue(dev);
                dev->trans_start = jiffies;
        }
        else
@@ -813,15 +810,6 @@ static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
        struct priv *p;
        int bcnt = 32;
 
-       if (dev == NULL) {
-               printk (KERN_ERR "ni65_interrupt(): irq %d for unknown device.\n", irq);
-               return;
-       }
-
-       if(test_and_set_bit(0,(int *) &dev->interrupt)) {
-               printk("ni65: oops .. interrupt while proceeding interrupt\n");
-               return;
-       }
        p = (struct priv *) dev->priv;
 
        while(--bcnt) {
@@ -916,8 +904,6 @@ static void ni65_interrupt(int irq, void * dev_id, struct pt_regs * regs)
        else
                writedatareg(CSR0_INEA);
 
-       dev->interrupt = 0;
-
        return;
 }
 
@@ -974,7 +960,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0)
 
 #ifdef XMT_VIA_SKB
                if(p->tmd_skb[p->tmdlast]) {
-                        dev_kfree_skb(p->tmd_skb[p->tmdlast]);
+                        dev_kfree_skb_irq(p->tmd_skb[p->tmdlast]);
                         p->tmd_skb[p->tmdlast] = NULL;
                }
 #endif
@@ -983,8 +969,7 @@ static void ni65_xmit_intr(struct net_device *dev,int csr0)
                if(p->tmdlast == p->tmdnum)
                        p->xmit_queued = 0;
        }
-       dev->tbusy = 0;
-       mark_bh(NET_BH);
+       netif_wake_queue(dev);
 }
 
 /*
@@ -1082,32 +1067,31 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
 /*
  * kick xmitter ..
  */
-static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
+static void ni65_timeout(struct net_device *dev)
 {
+       int i;
        struct priv *p = (struct priv *) dev->priv;
 
-       if(dev->tbusy)
-       {
-               int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 50)
-                       return 1;
+       printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
+       for(i=0;i<TMDNUM;i++)
+               printk("%02x ",p->tmdhead[i].u.s.status);
+       printk("\n");
+       ni65_lance_reinit(dev);
+       dev->trans_start = jiffies;
+       netif_wake_queue(dev);
+}
 
-               printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
-               {
-                       int i;
-                       for(i=0;i<TMDNUM;i++)
-                               printk("%02x ",p->tmdhead[i].u.s.status);
-                       printk("\n");
-               }
-               ni65_lance_reinit(dev);
-               dev->tbusy=0;
-               dev->trans_start = jiffies;
-       }
+/*
+ *     Send a packet
+ */
 
-       if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-                printk(KERN_ERR "%s: Transmitter access conflict.\n", dev->name);
-                return 1;
-       }
+static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+       struct priv *p = (struct priv *) dev->priv;
+
+       netif_stop_queue(dev);
+       
        if (test_and_set_bit(0, (void*)&p->lock)) {
                printk(KERN_ERR "%s: Queue was locked.\n", dev->name);
                return 1;
@@ -1152,7 +1136,9 @@ static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
                p->xmit_queued = 1;
                p->tmdnum = (p->tmdnum + 1) & (TMDNUM-1);
 
-               dev->tbusy = (p->tmdnum == p->tmdlast) ? 1 : 0;
+               if(p->tmdnum != p->tmdlast)
+                       netif_wake_queue(dev);
+                       
                p->lock = 0;
                dev->trans_start = jiffies;
 
@@ -1183,7 +1169,7 @@ static void set_multicast_list(struct net_device *dev)
 {
        if(!ni65_lance_reinit(dev))
                printk(KERN_ERR "%s: Can't switch card into MC mode!\n",dev->name);
-       dev->tbusy = 0;
+       netif_wake_queue(dev);
 }
 
 #ifdef MODULE
index 9dd2c188e2f1fa7677be1bbb2a0017e3f3766a73..f13b02889dafbe19aa9cf81b301c545a74568bb2 100644 (file)
@@ -115,6 +115,7 @@ static void fjn_rx(struct net_device *dev);
 static void fjn_reset(struct net_device *dev);
 static struct net_device_stats *fjn_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
+static void fjn_tx_timeout (struct net_device *dev);
 
 static dev_info_t dev_info = "fmvj18x_cs";
 static dev_link_t *dev_list = NULL;
@@ -139,6 +140,7 @@ typedef struct local_info_t {
     cardtype_t cardtype;
     u_short sent;
     u_char mc_filter[8];
+    spinlock_t lock;
 } local_info_t;
 
 #define MC_FILTERBREAK 64
@@ -235,6 +237,8 @@ typedef struct local_info_t {
 #define INTR_OFF             0x0d /* LAN controler ignores interrupts */
 #define INTR_ON              0x1d /* LAN controler will catch interrupts */
 
+#define TX_TIMEOUT          10
+
 /*======================================================================
 
     This bit of code is used to avoid unregistering network devices
@@ -278,6 +282,8 @@ static dev_link_t *fmvj18x_attach(void)
     lp = kmalloc(sizeof(*lp), GFP_KERNEL);
     if (!lp) return NULL;
     memset(lp, 0, sizeof(*lp));
+    
+    lp->lock = SPIN_LOCK_UNLOCKED;
     link = &lp->link; dev = &lp->dev;
     link->priv = dev->priv = link->irq.Instance = lp;
 
@@ -314,7 +320,9 @@ static dev_link_t *fmvj18x_attach(void)
     dev->init = &fmvj18x_init;
     dev->open = &fjn_open;
     dev->stop = &fjn_close;
-    dev->tbusy = 0xFF;
+    dev->tx_timeout = fjn_tx_timeout;
+    dev->watchdog_timeo = TX_TIMEOUT;
+    netif_start_queue (dev);
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -462,7 +470,7 @@ static void fmvj18x_config(dev_link_t *link)
     CS_CHECK(RequestConfiguration, link->handle, &link->conf);
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
-    dev->tbusy = 0;
+    netif_start_queue (dev);
     if (register_netdev(dev) != 0) {
        printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
        goto failed;
@@ -585,8 +593,7 @@ static int fmvj18x_event(event_t event, int priority,
     case CS_EVENT_CARD_REMOVAL:
        link->state &= ~DEV_PRESENT;
        if (link->state & DEV_CONFIG) {
-           dev->tbusy = 0xFF; 
-           dev->start = 0;
+           netif_stop_queue (dev);
            link->release.expires = jiffies + HZ/20;
            add_timer(&link->release);
        }
@@ -601,8 +608,7 @@ static int fmvj18x_event(event_t event, int priority,
     case CS_EVENT_RESET_PHYSICAL:
        if (link->state & DEV_CONFIG) {
            if (link->open) {
-               dev->tbusy = 0xFF; 
-               dev->start = 0;
+               netif_stop_queue (dev);
            }
            CardServices(ReleaseConfiguration, link->handle);
        }
@@ -614,9 +620,8 @@ static int fmvj18x_event(event_t event, int priority,
        if (link->state & DEV_CONFIG) {
            CardServices(RequestConfiguration, link->handle, &link->conf);
            if (link->open) {
-               dev->tbusy = 0;
-               dev->start = 1;
                fjn_reset(dev);
+               netif_start_queue (dev);
            }
        }
        break;
@@ -670,12 +675,9 @@ static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
               "unknown device.\n", irq);
         return;
     }
-    if (dev->interrupt) {
-        printk(KERN_NOTICE "%s: re-entering the interrupt handler.\n",
-              dev->name);
-        return;
-    }
-    dev->interrupt = 1;
+    
+    spin_lock (&lp->lock);
+    
     ioaddr = dev->base_addr;
 
     /* avoid multiple interrupts */
@@ -708,71 +710,65 @@ static void fjn_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);
        } else {
            lp->tx_started = 0;
-           dev->tbusy = 0;
-           mark_bh(NET_BH);    /* Inform upper layers. */
+           netif_stop_queue (dev);
        }
     }
     DEBUG(4, "%s: exiting interrupt,\n", dev->name);
     DEBUG(4, "    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
 
-    dev->interrupt = 0;
     outb(D_TX_INTR, ioaddr + TX_INTR);
     outb(D_RX_INTR, ioaddr + RX_INTR);
 
-    return;
+    spin_unlock (&lp->lock);
+    
 } /* fjn_interrupt */
 
 /*====================================================================*/
-
-static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void fjn_tx_timeout (struct net_device *dev)
 {
-    struct local_info_t *lp = (struct local_info_t *)dev->priv;
-    ioaddr_t 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 < 10)
-           return 1;
-       printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
-              dev->name, htons(inw(ioaddr + TX_STATUS)),
-              inb(ioaddr + TX_STATUS) & F_TMT_RDY
-              ? "IRQ conflict" : "network cable problem");
-       printk(KERN_NOTICE "%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)));
+       struct local_info_t *lp = (struct local_info_t *) dev->priv;
+       ioaddr_t ioaddr = dev->base_addr;
+       unsigned long flags;
+
+       printk (KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
+               dev->name, htons (inw (ioaddr + TX_STATUS)),
+               inb (ioaddr + TX_STATUS) & F_TMT_RDY
+               ? "IRQ conflict" : "network cable problem");
+       printk (KERN_NOTICE "%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)));
        lp->stats.tx_errors++;
+
        /* ToDo: We should try to restart the adaptor... */
-       cli();
+       spin_lock_irqsave (&lp->lock, flags);
 
-       fjn_reset(dev);
+       fjn_reset (dev);
 
        lp->tx_started = 0;
        lp->tx_queue = 0;
        lp->tx_queue_len = 0;
        lp->sent = 0;
        lp->open_time = jiffies;
-       dev->interrupt = 0;
-       dev->tbusy = 0;
-       dev->start = 1;
-    
-       sti();
-    }
+       netif_start_queue (dev);
+
+       spin_unlock_irqrestore (&lp->lock, flags);
+}
+
+
+static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+    struct local_info_t *lp = (struct local_info_t *)dev->priv;
+    ioaddr_t ioaddr = dev->base_addr;
 
-    /* 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(KERN_NOTICE "%s: Transmitter access conflict.\n", dev->name);
-    else {
+    netif_stop_queue (dev);
+    if (1) {
        short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        unsigned char *buf = skb->data;
 
@@ -806,17 +802,17 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
            lp->tx_queue_len = 0;
            dev->trans_start = jiffies;
            lp->tx_started = 1;
-           dev->tbusy = 0;
+           netif_start_queue (dev);
        } else {
            if( sram_config == 0 ) {
                if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
                    /* Yes, there is room for one more packet. */
-                   dev->tbusy = 0;
+                   netif_start_queue (dev);
            } else {
                if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && 
                                                lp->tx_queue < 127 )
                    /* Yes, there is room for one more packet. */
-                   dev->tbusy = 0;
+                   netif_start_queue (dev);
            }
        }
 
@@ -1025,9 +1021,7 @@ static int fjn_open(struct net_device *dev)
     lp->tx_queue = 0;
     lp->tx_queue_len = 0;
     lp->open_time = jiffies;
-    dev->interrupt = 0;
-    dev->tbusy = 0;
-    dev->start = 1;
+    netif_start_queue (dev);    
     
     MOD_INC_USE_COUNT;
 
@@ -1045,8 +1039,7 @@ static int fjn_close(struct net_device *dev)
     DEBUG(4, "fjn_close('%s').\n", dev->name);
 
     lp->open_time = 0;
-    dev->tbusy = 1;
-    dev->start = 0;
+    netif_stop_queue (dev);
 
     /* Set configuration register 0 to disable Tx and Rx. */
     if( sram_config == 0 ) 
@@ -1064,7 +1057,6 @@ static int fjn_close(struct net_device *dev)
        outb(INTR_OFF, ioaddr + LAN_CTRL);
 
     link->open--;
-    dev->start = 0;
     if (link->state & DEV_STALE_CONFIG) {
        link->release.expires = jiffies + HZ/20;
        link->state |= DEV_RELEASE_PENDING;
index 25ffb1c2c3ed8dbda908583c0d17ee54d5e9f735..282b5b0d6bcc5e46aec7019d2cf900a46321545d 100644 (file)
@@ -96,16 +96,7 @@ static int csr0 = 0x00A00000 | 0x4800;
 #endif
 
 #include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -140,9 +131,6 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
 #define RUN_AT(x) (jiffies + (x))
 
-#define NETSTATS_VER2
-#define PCI_SUPPORT_VER3
-
 #define tulip_debug debug
 #ifdef TULIP_DEBUG
 static int tulip_debug = TULIP_DEBUG;
@@ -2352,8 +2340,8 @@ static void tulip_tx_timeout(struct net_device *dev)
        outl(0, ioaddr + CSR1);
 
        dev->trans_start = jiffies;
+       netif_wake_queue (dev);
        tp->stats.tx_errors++;
-       return;
 }
 
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
index fad5b90ff2d9f62e7efd44502c6a2d781d0836a3..d284df6f60b655169286c4ded9e0f605dff0c482 100644 (file)
@@ -1,4 +1,4 @@
-/* rtl8139.c: A RealTek RTL8129/8139 Fast Ethernet driver for Linux. */
+/* rtl8129.c: A RealTek RTL8129 Fast Ethernet driver for Linux. */
 /*
        Written 1997-1999 by Donald Becker.
 
@@ -6,8 +6,7 @@
        of the GNU Public License, incorporated herein by reference.
     All other rights reserved.
 
-       This driver is for boards based on the RTL8129 and RTL8139 PCI ethernet
-       chips.
+       This driver is for boards based on the RTL8129 PCI ethernet chip.
 
        The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
        Center of Excellence in Space Data and Information Sciences
@@ -20,7 +19,7 @@
 */
 
 static const char *version =
-"rtl8139.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
+"rtl8129.c:v1.07 5/6/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/rtl8139.html\n";
 
 /* A few user-configurable values. */
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
@@ -66,6 +65,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <linux/ioport.h>
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -286,17 +286,13 @@ struct rtl8129_private {
        unsigned int mediasense:1;                      /* Media sensing in progress. */
 };
 
-#ifdef MODULE
-#if LINUX_VERSION_CODE > 0x20115
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("RealTek RTL8129/8139 Fast Ethernet driver");
+MODULE_DESCRIPTION("RealTek RTL8129 Fast Ethernet driver");
 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM(multicast_filter_limit, "i");
 MODULE_PARM(max_interrupt_work, "i");
 MODULE_PARM(debug, "i");
-#endif
-#endif
 
 static int rtl8129_open(struct net_device *dev);
 static int read_eeprom(long ioaddr, int location);
@@ -323,7 +319,7 @@ static struct net_device *root_rtl8129_dev = NULL;
    well when dynamically adding drivers.  So instead we detect just the
    Rtl81*9 cards in slot order. */
 
-int rtl8139_probe(void)
+static int __init rtl8129_probe(void)
 {
        int cards_found = 0;
        int pci_index = 0;
@@ -786,7 +782,7 @@ static void rtl8129_timer(unsigned long data)
        if (inw(ioaddr + IntrStatus) & (TxOK | RxOK)) {
                int status = inw(ioaddr + IntrStatus);
                if (status & (TxOK | RxOK)) {   /* Double check */
-                       printk(KERN_ERR "%s: RTL8139 Interrupt line blocked, status %x.\n",
+                       printk(KERN_ERR "%s: RTL8129 Interrupt line blocked, status %x.\n",
                                   dev->name, status);
                        rtl8129_interrupt(dev->irq, dev, 0);
                }
@@ -1438,14 +1434,8 @@ static void set_rx_mode(struct net_device *dev)
        return;
 }
 \f
-#ifdef MODULE
-int init_module(void)
-{
-       return rtl8139_probe();
-}
 
-void
-cleanup_module(void)
+static void __exit rtl8129_cleanup (void)
 {
        struct net_device *next_dev;
 
@@ -1463,12 +1453,13 @@ cleanup_module(void)
        }
 }
 
-#endif  /* MODULE */
-\f
+module_init(rtl8129_probe);
+module_exit(rtl8129_cleanup);
+
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8139.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8129.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  SMP-compile-command: "gcc -D__SMP__ -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c rtl8129.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
index 4d391cf2b0eed992369a3184bebbd4b60e624f63..ee941f451d2bba807ad0486c61903d45c9dbd70e 100644 (file)
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:   1.06.03 Dec 23 1999
+   Revision:   1.06.04 Feb 11 2000
    
    Modified from the driver which is originally written by Donald Becker. 
    
@@ -135,7 +135,7 @@ struct sis900_private {
        int LinkOn;
 };
 
-MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>");
+MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
 MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
 MODULE_PARM(multicast_filter_limit, "i");
 MODULE_PARM(max_interrupt_work, "i");
@@ -257,7 +257,7 @@ static struct net_device * sis900_mac_probe (struct mac_chip_info * mac, struct
        net_dev->irq = irq;
        sis_priv->pci_dev = pci_dev;
        sis_priv->mac = mac;
-       sis_priv->lock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&sis_priv->lock);
 
        /* probe for mii transciver */
        if (sis900_mii_probe(net_dev) == 0) {
@@ -668,8 +668,8 @@ static void sis900_timer(unsigned long data)
                next_tick = 5*HZ;
                /* change what cur_phy means */
                if (mii_phy->phy_addr != sis_priv->cur_phy) {
-                       printk(KERN_INFO "%s: Changing transceiver to %s\n", net_dev->name,
-                              mii_phy->chip_info->name);
+                       printk(KERN_INFO "%s: Changing transceiver to %s\n",
+                              net_dev->name, mii_phy->chip_info->name);
                        status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
                        mdio_write(net_dev, sis_priv->cur_phy, 
                                   MII_CONTROL, status | MII_CNTL_ISOLATE);
@@ -798,9 +798,10 @@ static void sis900_tx_timeout(struct net_device *net_dev)
        /* Disable interrupts by clearing the interrupt mask. */
        outl(0x0000, ioaddr + imr);
 
-       /* discard unsent packets, should this code section be protected by
-          cli(), sti() ?? */
+       /* use spinlock to prevent interrupt handler accessing buffer ring */
        spin_lock_irqsave(&sis_priv->lock, flags);
+
+       /* discard unsent packets */
        sis_priv->dirty_tx = sis_priv->cur_tx = 0;
        for (i = 0; i < NUM_TX_DESC; i++) {
                if (sis_priv->tx_skbuff[i] != NULL) {
@@ -811,13 +812,15 @@ static void sis900_tx_timeout(struct net_device *net_dev)
                        sis_priv->stats.tx_dropped++;
                }
        }
+       sis_priv->tx_full = 0;
+       netif_wake_queue(net_dev);
+
        spin_unlock_irqrestore(&sis_priv->lock, flags);
 
        net_dev->trans_start = jiffies;
-       sis_priv->tx_full = 0;
-       netif_start_queue(net_dev);
 
        /* FIXME: Should we restart the transmission thread here  ?? */
+       outl(TxENA, ioaddr + cr);
 
        /* Enable all known interrupts by setting the interrupt mask. */
        outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
@@ -830,6 +833,9 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
        long ioaddr = net_dev->base_addr;
        unsigned int  entry;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sis_priv->lock, flags);
 
        /* Calculate the next Tx descriptor entry. */
        entry = sis_priv->cur_tx % NUM_TX_DESC;
@@ -841,14 +847,16 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        outl(TxENA, ioaddr + cr);
 
        if (++sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC) {
-               /* Typical path, clear tbusy to indicate more 
-                  transmission is possible */
+               /* Typical path, tell upper layer that more transmission is possible */
                netif_start_queue(net_dev);
        } else {
-               /* no more transmit descriptor avaiable, tbusy remain set */
+               /* buffer full, tell upper layer no more transmission */
                sis_priv->tx_full = 1;
+               netif_stop_queue(net_dev);
        }
 
+       spin_unlock_irqrestore(&sis_priv->lock, flags);
+
        net_dev->trans_start = jiffies;
 
        if (sis900_debug > 3)
@@ -922,7 +930,7 @@ static int sis900_rx(struct net_device *net_dev)
        if (sis900_debug > 3)
                printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
                       "status:0x%8.8x\n",
-                      sis_priv->cur_rx, sis_priv->dirty_rx,rx_status);
+                      sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
        
        while (rx_status & OWN) {
                unsigned int rx_size;
@@ -1060,8 +1068,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
        
        if (sis_priv->tx_full && test_bit(LINK_STATE_XOFF, &net_dev->flags) && 
            sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
-               /* The ring is no longer full, clear tbusy, tx_full and
-                  schedule more transmission by marking NET_BH */
+               /* The ring is no longer full, clear tx_full and schedule more transmission
+                  by netif_wake_queue(net_dev) */
                sis_priv->tx_full = 0;
                netif_wake_queue (net_dev);
        }
index 24dd1ff1c1f5302063ba67b49f378235e152fac3..d3722cf2d776ee6e3632a9a9c1281ff431de0bd9 100644 (file)
@@ -472,6 +472,7 @@ static spinlock_t SK_lock = SPIN_LOCK_UNLOCKED;
 int          SK_init(struct net_device *dev);
 static int   SK_probe(struct net_device *dev, short ioaddr);
 
+static void  SK_timeout(struct net_device *dev);
 static int   SK_open(struct net_device *dev);
 static int   SK_send_packet(struct sk_buff *skb, struct net_device *dev);
 static void  SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
@@ -778,11 +779,13 @@ int __init SK_probe(struct net_device *dev, short ioaddr)
 
     /* Assign our Device Driver functions */
 
-    dev->open                   = &SK_open;
-    dev->stop                   = &SK_close;
-    dev->hard_start_xmit        = &SK_send_packet;
-    dev->get_stats              = &SK_get_stats;
-    dev->set_multicast_list     = &set_multicast_list;
+    dev->open                   = SK_open;
+    dev->stop                   = SK_close;
+    dev->hard_start_xmit        = SK_send_packet;
+    dev->get_stats              = SK_get_stats;
+    dev->set_multicast_list     = set_multicast_list;
+    dev->tx_timeout            = SK_timeout;
+    dev->watchdog_timeo                = HZ/7;
 
 
     /* Set the generic fields of the device structure */
@@ -1169,30 +1172,18 @@ static int SK_lance_init(struct net_device *dev, unsigned short mode)
  *     YY/MM/DD  uid  Description
 -*/
 
-static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
+static int SK_timeout(struct net_device *dev)
 {
-    struct priv *p = (struct priv *) dev->priv;
-    struct tmd *tmdp;
-
-    if (test_bit(LINK_STATE_XOFF, &dev->flags))
-    {
-       /* if Transmitter more than 150ms busy -> time_out */
-
-       int tickssofar = jiffies - dev->trans_start;
-       if (tickssofar < 15)
-       {
-           return 1;                    /* We have to try transmit later */
-       }
-
-       printk("%s: xmitter timed out, try to restart!\n", dev->name);
-
+       printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);
        SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
-
        netif_start_queue(dev);          /* Clear Transmitter flag */
-
        dev->trans_start = jiffies;      /* Mark Start of transmission */
+}
 
-    }
+static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+    struct priv *p = (struct priv *) dev->priv;
+    struct tmd *tmdp;
 
     PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", 
            SK_NAME, SK_read_reg(CSR0)));
index 4e3847f2eeed41bd26175c5df604fed578b72dfd..cf9b4e47d8a212f697d4967087baf4bc183b3cd6 100644 (file)
@@ -102,12 +102,6 @@ static int rx_copybreak = 100;
 #define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
 #endif
 
-/* This my implementation of shared IRQs, now only used for 1.2.13. */
-#ifdef HAVE_SHARED_IRQ
-#define USE_SHARED_IRQ
-#include <linux/shared_irq.h>
-#endif
-
 /* The total size is unusually large: The 21040 aligns each of its 16
    longword-wide registers on a quadword boundary. */
 #define TULIP_TOTAL_SIZE 0x80
index 47196db9c7fb23ac2cfe8ae79423e526ec140ccf..d87703d0d0aab076b443be2beb927a118b2a0ec4 100644 (file)
@@ -93,6 +93,9 @@
 /* This is an extension of the 'struct net_device' we create for each network
    interface to keep the rest of X.25 channel-specific data. */
 typedef struct x25_channel {
+       /* This member must be first. */
+       struct net_device *slave;       /* WAN slave */
+
        char name[WAN_IFNAME_SZ+1];     /* interface name, ASCIIZ */
        char addr[WAN_ADDRESS_SZ+1];    /* media address, ASCIIZ */
        char *local_addr;               /* local media address, ASCIIZ -
@@ -1253,11 +1256,13 @@ static int x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len, void *buf)
 static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
 {
        struct net_device *dev = wandev->dev;
+       x25_channel_t *chan;
 
-       for (; dev; dev = dev->slave)
-               if (((x25_channel_t*)dev->priv)->lcn == lcn)
+       while (dev) {
+               if (chan->lcn == lcn)
                        break;
-       
+               dev = chan->slave;
+       }       
        return dev;
 }
 
@@ -1265,11 +1270,13 @@ static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
 static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
 {
        struct net_device *dev = wandev->dev;
+       x25_channel_t *chan;
 
-       for (; dev; dev = dev->slave)
-               if (!strcmp(((x25_channel_t*)dev->priv)->addr, dte))
+       while (dev) {
+               if (!strcmp(chan->addr, dte))
                        break;
-
+               dev = chan->slave;
+       }
        return dev;
 }
 
@@ -1553,12 +1560,13 @@ static void x25_dump_devs(wan_device_t *wandev)
        printk(KERN_INFO "name: addr:           txoff:  protocol:\n");
        printk(KERN_INFO "---------------------------------------\n");
 
-       for (; dev; dev = dev->slave) {
+       while(dev) {
                x25_channel_t *chan = dev->priv;
 
                printk(KERN_INFO "%-5.5s %-15.15s   %d     ETH_P_%s\n",
                                 chan->name, chan->addr, test_bit(LINK_STATE_XOFF, &dev->state),
                                 chan->protocol == ETH_P_IP ? "IP" : "X25");
+               dev = chan->slave;
        }
 }
 
index 3df910ea132821119d69ebc8e038d2e6c45471a4..c0b419afa80c20475bd6cd3165d89741015a8257 100644 (file)
@@ -74,6 +74,9 @@
 
 typedef struct chdlc_private_area
 {
+       /* This member must be first. */
+       struct net_device *slave;               /* WAN slave */
+
        sdla_t          *card;
        int             TracingEnabled;         /* For enabling Tracing */
        unsigned long   curr_trace_addr;        /* Used for Tracing */
index 0c7f7e8f000332a3718ec74033d2ef674ab171b8..f4431c9dcd61b325e9766608a7a307920347aee3 100644 (file)
  */
 typedef struct fr_channel
 {
+       /* This member must be first. */
+       struct net_device *slave;       /* WAN slave */
+
        char name[WAN_IFNAME_SZ+1];     /* interface name, ASCIIZ */
        unsigned dlci_configured  ;     /* check whether configured or not */
        unsigned cir_status;            /* check whether CIR enabled or not */
@@ -1960,7 +1963,9 @@ goto L4;
        // Used to send inarp request at given interval 
        if (card->wandev.state == WAN_CONNECTED) {
                int num_remaining = 0;
-                for (dev=card->wandev.dev;dev;dev=dev->slave) {
+
+               dev = card->wandev.dev;
+               while (dev) {
                        fr_channel_t *chan = dev->priv;
 
                         if (chan->inarp == INARP_REQUEST &&
@@ -1972,6 +1977,7 @@ goto L4;
                                        chan->inarp_tick = jiffies;
                                 }
                        }
+                       dev = chan->slave;
                }
                if (!num_remaining) {   // no more to process 
                         flags->imask &= ~FR_INTR_TIMER;
@@ -2135,65 +2141,68 @@ static void process_route (sdla_t* card)
 
 
        /* Dynamic Route adding/removing */
-       for (dev = card->wandev.dev; dev ; dev = dev->slave) {
-            if ( ((fr_channel_t*)dev->priv)->route_flag == ADD_ROUTE   ||
-               ((fr_channel_t*)dev->priv)->route_flag == REMOVE_ROUTE ) {
-               fs = get_fs();
+       dev = card->wandev.dev;
+       while (dev) {
+               fr_channel_t *chan = dev->priv;
+
+               if (chan->route_flag == ADD_ROUTE   ||
+                   chan->route_flag == REMOVE_ROUTE ) {
+                       fs = get_fs();
                
-               in_dev = dev->ip_ptr;
-
-               if( in_dev != NULL && in_dev->ifa_list != NULL) {
-                       memset(&route, 0, sizeof(route));
-                       route.rt_dev   = dev->name;
-                       route.rt_flags = 0;
-
-                       ((struct sockaddr_in *) &(route.rt_dst)) ->
-                               sin_addr.s_addr=in_dev->ifa_list->ifa_address;
-                       ((struct sockaddr_in *) &(route.rt_dst)) ->
-                               sin_family = AF_INET;
-                       ((struct sockaddr_in *) &(route.rt_genmask)) ->
-                               sin_addr.s_addr = 0xFFFFFFFF;
-                       ((struct sockaddr_in *) &(route.rt_genmask)) ->
-                               sin_family = AF_INET;
-
-                       switch(((fr_channel_t*)dev->priv)->route_flag) {
-
-                       case ADD_ROUTE:
-                               set_fs(get_ds());     /* get user space block */
-                               err = ip_rt_ioctl( SIOCADDRT, &route);  
-                               set_fs(fs);           /* restore old block */
-
-                               if (err) {
-                                       printk(KERN_INFO "%s: Adding of route failed.  Error: %d\n", card->devname,err);
-                                       printk(KERN_INFO "%s: Address: %s\n",
-                                       ((fr_channel_t*)dev->priv)->name,
-                                       in_ntoa(in_dev->ifa_list->ifa_address) );
-                               }
-                               else {
-                                       ((fr_channel_t*)dev->priv)->
-                                               route_flag = ROUTE_ADDED;
-                               }
-                               break;
+                       in_dev = dev->ip_ptr;
+
+                       if( in_dev != NULL && in_dev->ifa_list != NULL) {
+                               memset(&route, 0, sizeof(route));
+                               route.rt_dev   = dev->name;
+                               route.rt_flags = 0;
+
+                               ((struct sockaddr_in *) &(route.rt_dst)) ->
+                                       sin_addr.s_addr=in_dev->ifa_list->ifa_address;
+                               ((struct sockaddr_in *) &(route.rt_dst)) ->
+                                       sin_family = AF_INET;
+                               ((struct sockaddr_in *) &(route.rt_genmask)) ->
+                                       sin_addr.s_addr = 0xFFFFFFFF;
+                               ((struct sockaddr_in *) &(route.rt_genmask)) ->
+                                       sin_family = AF_INET;
+
+                               switch(chan->route_flag) {
+
+                               case ADD_ROUTE:
+                                       set_fs(get_ds());     /* get user space block */
+                                       err = ip_rt_ioctl( SIOCADDRT, &route);  
+                                       set_fs(fs);           /* restore old block */
+
+                                       if (err) {
+                                               printk(KERN_INFO "%s: Adding of route failed.  Error: %d\n", card->devname,err);
+                                               printk(KERN_INFO "%s: Address: %s\n",
+                                                      chan->name,
+                                                      in_ntoa(in_dev->ifa_list->ifa_address) );
+                                       } else {
+                                               chan->route_flag = ROUTE_ADDED;
+                                       }
+                                       break;
 
-                       case REMOVE_ROUTE:
-                               set_fs(get_ds());     /* get user space block */
-                               err = ip_rt_ioctl( SIOCDELRT, &route);
-                               set_fs(fs);           /* restore old block */
+                               case REMOVE_ROUTE:
+                                       set_fs(get_ds());     /* get user space block */
+                                       err = ip_rt_ioctl( SIOCDELRT, &route);
+                                       set_fs(fs);           /* restore old block */
+
+                                       if (err) {
+                                               printk(KERN_INFO "%s: Deleting of route failed.  Error: %d\n", card->devname,err);
+                                               printk(KERN_INFO "%s: Address: %s\n",
+                                                      dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
+                                       } else {
+                                               printk(KERN_INFO "%s: Removed route.\n",
+                                                      chan->name);
+                                               chan->route_flag = NO_ROUTE;
+                                       }
+                                       break;
+                               } /* Case Statement */
+                       }
+               } /* If ADD/DELETE ROUTE */
 
-                               if (err) {
-                                       printk(KERN_INFO "%s: Deleting of route failed.  Error: %d\n", card->devname,err);
-                                       printk(KERN_INFO "%s: Address: %s\n",
-                                       dev->name,in_ntoa(in_dev->ifa_list->ifa_address) );
-                               } else {
-                                       printk(KERN_INFO "%s: Removed route.\n",
-                                       ((fr_channel_t*)dev->priv)->name);
-                                       ((fr_channel_t*)dev->priv)->route_flag = NO_ROUTE;
-                               }
-                               break;
-                       } /* Case Statement */
-               }
-            } /* If ADD/DELETE ROUTE */
-       }  /* Device 'For' Loop */
+               dev = chan->slave;
+       }  /* Device 'While' Loop */
 
        card->poll = NULL;
 }
@@ -2568,7 +2577,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
                        struct net_device *dev;
 
                        /* Remove all routes from associated DLCI's */
-                       for (dev = card->wandev.dev; dev; dev = dev->slave) {
+                       dev = card->wandev.dev;
+                       while (dev) {
                                fr_channel_t *chan = dev->priv;
                                if (chan->route_flag == ROUTE_ADDED) {
                                        chan->route_flag = REMOVE_ROUTE;
@@ -2578,6 +2588,8 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
                                if (chan->inarp == INARP_CONFIGURED) {
                                        chan->inarp = INARP_REQUEST;
                                }
+
+                               dev = chan->slave;
                        }
 
                        wanpipe_set_state(card, WAN_DISCONNECTED);
@@ -2590,12 +2602,14 @@ static int fr_event (sdla_t *card, int event, fr_mbox_t* mbox)
                        int num_requests = 0;
 
                        /* Remove all routes from associated DLCI's */
-                       for (dev = card->wandev.dev; dev; dev = dev->slave) {
+                       dev = card->wandev.dev;
+                       while (dev) {
                                fr_channel_t *chan = dev->priv; 
                                if( chan->inarp == INARP_REQUEST ){
                                        num_requests++;
                                        chan->inarp_tick = jiffies;
                                }
+                               dev = chan->slave;
                        }
 
                        /* Allow timer interrupts */
@@ -2731,8 +2745,8 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
                }
        }
        
-       for (dev2 =card->wandev.dev; dev2; dev2 = dev2->slave){
-               
+       dev2 = card->wandev.dev;
+       while (dev2) {
                chan = dev2->priv;
        
                if (chan->dlci_configured == DLCI_CONFIG_PENDING) {
@@ -2741,6 +2755,7 @@ static int fr_dlci_change (sdla_t *card, fr_mbox_t* mbox)
                        }
                }
 
+               dev2 = chan->slave;
        }
        return 1;
 }
index 1b900fc626e71b8d2ec3165b0f57a6587bf62766..f3dcc129bba8a4c8760774ee573689f650940a1e 100644 (file)
   
 typedef struct ppp_private_area
 {
+       /* This member must be first. */
+       struct net_device *slave;       /* WAN slave */
+
        sdla_t* card;   
        unsigned long router_start_time;        /*router start time in sec */
        unsigned long tick_counter;             /*used for 5 second counter*/
index 270c5a59ff19af3cba6f2c89bfd4bd6e1f7d2f46..dfb5d36a52b1614f46c699897942c1c1d618476a 100644 (file)
@@ -75,6 +75,9 @@
  */
 typedef struct x25_channel
 {
+       /* This member must be first. */
+       struct net_device *slave;       /* WAN slave */
+
        char name[WAN_IFNAME_SZ+1];     /* interface name, ASCIIZ */
        char addr[WAN_ADDRESS_SZ+1];    /* media address, ASCIIZ */
        unsigned lcn;                   /* logical channel number */
@@ -708,11 +711,13 @@ static int if_send (struct sk_buff* skb, struct net_device* dev)
                        return dev->tbusy;
                }
                printk(KERN_INFO "%s: Transmit time out %s!\n",
-                       card->devname, dev->name)
-               ;
-               for( dev2 = card->wandev.dev; dev2; dev2 = dev2->slave)
-               {
+                      card->devname, dev->name);
+
+               dev2 = card->wandev.dev;
+               while (dev2) {
+                       x25_channel_t *chan2 = dev2->priv;
                        dev2->tbusy = 0;
+                       dev2 = chan2->slave;
                }
        }
        chan->tick_counter = jiffies;
@@ -898,13 +903,17 @@ static void wpx_isr (sdla_t* card)
 
        if(card->buff_int_mode_unbusy)
        {
-               for(dev = card->wandev.dev; dev; dev = dev->slave)
-               {
-                       if(((x25_channel_t*)dev->priv)->devtint)
-                       {
+               x25_channel_t *chan;
+
+               dev = card->wandev.dev;
+               while (dev) {
+                       chan = dev->priv;
+                       if(chan->devtint) {
                                mark_bh(NET_BH);
                                return;
                        }       
+
+                       dev = chan->slave;
                }
        }
 }
@@ -1042,12 +1051,15 @@ static void rx_intr (sdla_t* card)
 static void tx_intr (sdla_t* card)
 {
        struct net_device *dev;
+       x25_channel_t *chan;
 
        /* unbusy all devices and then dev_tint(); */
-       for(dev = card->wandev.dev; dev; dev = dev->slave)
-       {
-               ((x25_channel_t*)dev->priv)->devtint = dev->tbusy; 
+       dev = card->wandev.dev;
+       while (dev) {
+               chan->devtint = dev->tbusy; 
                dev->tbusy = 0;
+
+               dev = chan->slave;
        }
 
 }
@@ -1170,8 +1182,8 @@ static void poll_active (sdla_t* card)
        /* Fetch X.25 asynchronous events */
        x25_fetch_events(card);
 
-       for (dev = card->wandev.dev; dev; dev = dev->slave)
-       {
+       dev = card->wandev.dev;
+       while (dev) {
                x25_channel_t* chan = dev->priv;
                struct sk_buff* skb = chan->tx_skb;
 
@@ -1199,6 +1211,8 @@ static void poll_active (sdla_t* card)
                                chan_disc(dev);
                        }
                }
+
+               dev = chan->slave;
        }
 }
 
@@ -1785,8 +1799,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
                card->devname, new_lcn, mb->data);
 
        /* Find available channel */
-       for (dev = wandev->dev; dev; dev = dev->slave)
-       {
+       dev = wandev->dev;
+       while (dev) {
                chan = dev->priv;
 
                if (!chan->svc || (chan->state != WAN_DISCONNECTED))
@@ -1796,6 +1810,8 @@ static int incoming_call (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
                /* If just an '@' is specified, accept all incoming calls */
                if (strcmp(chan->addr, "") == 0)
                        break;
+
+               dev = chan->slave;
        }
 
        if (dev == NULL)
@@ -1912,8 +1928,14 @@ static int restart_event (sdla_t* card, int cmd, int lcn, TX25Mbox* mb)
                card->devname, mb->cmd.cause, mb->cmd.diagn);
 
        /* down all logical channels */
-       for (dev = wandev->dev; dev; dev = dev->slave)
+       dev = wandev->dev;
+       while (dev) {
+               x25_channel_t *chan = dev->priv;
+
                set_chan_state(dev, WAN_DISCONNECTED);
+               dev = chan->slave;
+       }
+
        return (cmd == X25_WRITE) ? 0 : 1;
 }
 
@@ -1979,10 +2001,14 @@ static int disconnect (sdla_t* card)
 static struct net_device* get_dev_by_lcn (wan_device_t* wandev, unsigned lcn)
 {
        struct net_device* dev;
+       x25_channel_t *chan;
 
-       for (dev = wandev->dev; dev; dev = dev->slave)
-               if (((x25_channel_t*)dev->priv)->lcn == lcn)
+       dev = wandev->dev;
+       while (dev) {
+               if (chan->lcn == lcn)
                        break;
+               dev = chan->slave;
+       }
        return dev;
 }
 
index b6a058c031aab0836d7d2ebc1e564c2f457f0648..d87bf6d70631872436cb0df3ee4a4b280957bf50 100644 (file)
@@ -910,7 +910,7 @@ static inline int port_detect \
    if (info.sign != EATA_SIGNATURE) return FALSE;
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
-      printk("%s: config structure size (%ld bytes) too short, detaching.\n",
+      printk("%s: config structure size (%d bytes) too short, detaching.\n",
              name, DEV2H(info.data_len));
       return FALSE;
       }
index 191e4469ed7de7fb83e9fa7c9df2f4b1b5e9bdfe..e18b2e6d0452bc5eeb0467a1f9ab1a3376ee7d5c 100644 (file)
@@ -504,6 +504,15 @@ extern void scsi_unregister_module(int, void *);
  * tackle the character devices first, as there aren't any locking implications
  * in the block device layer.   The block devices will require more work.
  */
+#ifndef CONFIG_SD_EXTRA_DEVS
+#define CONFIG_SD_EXTRA_DEVS 2
+#endif
+#ifndef CONFIG_ST_EXTRA_DEVS
+#define CONFIG_ST_EXTRA_DEVS 2
+#endif
+#ifndef CONFIG_SR_EXTRA_DEVS
+#define CONFIG_SR_EXTRA_DEVS 2
+#endif
 #define SD_EXTRA_DEVS CONFIG_SD_EXTRA_DEVS
 #define ST_EXTRA_DEVS CONFIG_ST_EXTRA_DEVS
 #define SR_EXTRA_DEVS CONFIG_SR_EXTRA_DEVS
index a1177c6df280eb94904814af4c9d0e352782f9a8..eb0b3d27bac8f40620499899551dc34ae4f796be 100644 (file)
  *     along with this program; if not, write to the Free Software
  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  History
- *     Jan 14 2000 Ollie Lho <ollie@sis.com.tw> 
- *     Isloated from trident.c to support multiple ac97 codec
+ * History
+ * v0.2 Feb 10 2000 Ollie Lho
+ *     add ac97_read_proc for /proc/driver/vnedor/ac97
+ * v0.1 Jan 14 2000 Ollie Lho <ollie@sis.com.tw> 
+ *     Isolated from trident.c to support multiple ac97 codec
  */
 #include <linux/module.h>
 #include <linux/version.h>
@@ -40,7 +42,7 @@ static struct {
        unsigned int id;
        char *name;
        int  (*init)  (struct ac97_codec *codec);
-} snd_ac97_codec_ids[] = {
+} ac97_codec_ids[] = {
        {0x414B4D00, "Asahi Kasei AK4540"     , NULL},
        {0x41445340, "Analog Devices AD1881"  , NULL},
        {0x43525900, "Cirrus Logic CS4297"    , NULL},
@@ -52,9 +54,46 @@ static struct {
        {0x83847605, "SigmaTel STAC9704"      , NULL},
        {0x83847608, "SigmaTel STAC9708"      , NULL},
        {0x83847609, "SigmaTel STAC9721/23"   , NULL},
+       {0x54524108, "TriTech TR28028"        , NULL},
+       {0x574D4C00, "Wolfson WM9704"         , NULL},
        {0x00000000, NULL, NULL}
 };
 
+static const char *ac97_stereo_enhancements[] =
+{
+       /*   0 */ "No 3D Stereo Enhancement",
+       /*   1 */ "Analog Devices Phat Stereo",
+       /*   2 */ "Creative Stereo Enhancement",
+       /*   3 */ "National Semi 3D Stereo Enhancement",
+       /*   4 */ "YAMAHA Ymersion",
+       /*   5 */ "BBE 3D Stereo Enhancement",
+       /*   6 */ "Crystal Semi 3D Stereo Enhancement",
+       /*   7 */ "Qsound QXpander",
+       /*   8 */ "Spatializer 3D Stereo Enhancement",
+       /*   9 */ "SRS 3D Stereo Enhancement",
+       /*  10 */ "Platform Tech 3D Stereo Enhancement",
+       /*  11 */ "AKM 3D Audio",
+       /*  12 */ "Aureal Stereo Enhancement",
+       /*  13 */ "Aztech 3D Enhancement",
+       /*  14 */ "Binaura 3D Audio Enhancement",
+       /*  15 */ "ESS Technology Stereo Enhancement",
+       /*  16 */ "Harman International VMAx",
+       /*  17 */ "Nvidea 3D Stereo Enhancement",
+       /*  18 */ "Philips Incredible Sound",
+       /*  19 */ "Texas Instruments 3D Stereo Enhancement",
+       /*  20 */ "VLSI Technology 3D Stereo Enhancement",
+       /*  21 */ "TriTech 3D Stereo Enhancement",
+       /*  22 */ "Realtek 3D Stereo Enhancement",
+       /*  23 */ "Samsung 3D Stereo Enhancement",
+       /*  24 */ "Wolfson Microelectronics 3D Enhancement",
+       /*  25 */ "Delta Integration 3D Enhancement",
+       /*  26 */ "SigmaTel 3D Enhancement",
+       /*  27 */ "Reserved 27",
+       /*  28 */ "Rockwell 3D Stereo Enhancement",
+       /*  29 */ "Reserved 29",
+       /*  30 */ "Reserved 30",
+       /*  31 */ "Reserved 31"
+};
 
 /* this table has default mixer values for all OSS mixers. */
 static struct mixer_defaults {
@@ -86,9 +125,9 @@ static struct ac97_mixer_hw {
 } ac97_hw[SOUND_MIXER_NRDEVICES]= {
        [SOUND_MIXER_VOLUME]    =       {AC97_MASTER_VOL_STEREO,63},
        [SOUND_MIXER_BASS]      =       {AC97_MASTER_TONE,      15},
-       [SOUND_MIXER_TREBLE]    =       {AC97_MASTER_TONE,      15},
+       [SOUND_MIXER_TREBLE]    =       {AC97_MASTER_TONE,      15},
        [SOUND_MIXER_PCM]       =       {AC97_PCMOUT_VOL,       31},
-       [SOUND_MIXER_SPEAKER]   =       {AC97_PCBEEP_VOL,       15},
+       [SOUND_MIXER_SPEAKER]   =       {AC97_PCBEEP_VOL,       15},
        [SOUND_MIXER_LINE]      =       {AC97_LINEIN_VOL,       31},
        [SOUND_MIXER_MIC]       =       {AC97_MIC_VOL,          31},
        [SOUND_MIXER_CD]        =       {AC97_CD_VOL,           31},
@@ -155,10 +194,13 @@ static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel)
                        right = 100 - ((right * 100) / mh->scale);
                        left = 100 - ((left * 100) / mh->scale);
                }
-
                ret = left | (right << 8);
        } else if (oss_channel == SOUND_MIXER_SPEAKER) {
                ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
+       } else if (oss_channel == SOUND_MIXER_PHONEIN) {
+               ret = 100 - (((val & 0x1f) * 100) / mh->scale);
+       } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
+               ret = 100 - (((val & 0x1f) * 100) / mh->scale);
        } else if (oss_channel == SOUND_MIXER_MIC) {
                ret = 100 - (((val & 0x1f) * 100) / mh->scale);
                /*  the low bit is optional in the tone sliders and masking
@@ -200,10 +242,14 @@ static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
                } else {
                        right = ((100 - right) * mh->scale) / 100;
                        left = ((100 - left) * mh->scale) / 100;
-               }
+               }                       
                val = (left << 8) | right;
        } else if (oss_channel == SOUND_MIXER_SPEAKER) {
                val = (((100 - left) * mh->scale) / 100) << 1;
+       } else if (oss_channel == SOUND_MIXER_PHONEIN) {
+               val = (((100 - left) * mh->scale) / 100);
+       } else if (oss_channel == SOUND_MIXER_PHONEOUT) {
+               val = (((100 - left) * mh->scale) / 100);
        } else if (oss_channel == SOUND_MIXER_MIC) {
                val = codec->codec_read(codec , mh->offset) & ~0x801f;
                val |= (((100 - left) * mh->scale) / 100);
@@ -212,11 +258,10 @@ static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
        } else if (oss_channel == SOUND_MIXER_BASS) {
                val = codec->codec_read(codec , mh->offset) & ~0x0f00;
                val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
-       } else if (oss_channel == SOUND_MIXER_TREBLE)    {
+       } else if (oss_channel == SOUND_MIXER_TREBLE) {
                val = codec->codec_read(codec , mh->offset) & ~0x000f;
                val |= (((100 - left) * mh->scale) / 100) & 0x000e;
        }
-
 #ifdef DEBUG
        printk(" 0x%04x", val);
 #endif
@@ -335,11 +380,11 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned
                                return -EINVAL;
 
                        /* do we ever want to touch the hardware? */
-                       /* val = codec->read_mixer(card,i); */
-                       val = codec->mixer_state[i];
+                       val = codec->read_mixer(card, i);
+                       /* val = codec->mixer_state[i]; */
                        break;
                }
-               return put_user(val,(int *)arg);
+               return put_user(val, (int *)arg);
        }
 
        if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
@@ -368,6 +413,76 @@ static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned
        return -EINVAL;
 }
 
+/* entry point for /proc/driver/controller_vendor/ac97/%d */
+int ac97_read_proc (char *page, char **start, off_t off,
+                   int count, int *eof, void *data)
+{
+       int len = 0, cap, extid, val, id1, id2;
+       struct ac97_codec *codec;
+
+       if ((codec = data) == NULL)
+               return -ENODEV;
+
+       id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
+       id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
+       len += sprintf (page+len, "Vendor name      : %s\n", codec->name);
+       len += sprintf (page+len, "Vendor id        : %04X %04X\n", id1, id2);
+
+       extid = codec->codec_read(codec, AC97_EXTENDED_ID);
+       extid &= ~((1<<2)|(1<<4)|(1<<5)|(1<<10)|(1<<11)|(1<<12)|(1<<13));
+       len += sprintf (page+len, "AC97 Version     : %s\n",
+                       extid ? "2.0 or later" : "1.0");
+
+       cap = codec->codec_read(codec, AC97_RESET);
+       len += sprintf (page+len, "Capabilities     :%s%s%s%s%s%s\n",
+                       cap & 0x0001 ? " -dedicated MIC PCM IN channel-" : "",
+                       cap & 0x0002 ? " -reserved1-" : "",
+                       cap & 0x0004 ? " -bass & treble-" : "",
+                       cap & 0x0008 ? " -simulated stereo-" : "",
+                       cap & 0x0010 ? " -headphone out-" : "",
+                       cap & 0x0020 ? " -loudness-" : "");
+       val = cap & 0x00c0;
+       len += sprintf (page+len, "DAC resolutions  :%s%s%s\n",
+                       " -16-bit-",
+                       val & 0x0040 ? " -18-bit-" : "",
+                       val & 0x0080 ? " -20-bit-" : "");
+       val = cap & 0x0300;
+       len += sprintf (page+len, "ADC resolutions  :%s%s%s\n",
+                       " -16-bit-",
+                       val & 0x0100 ? " -18-bit-" : "",
+                       val & 0x0200 ? " -20-bit-" : "");
+       len += sprintf (page+len, "3D enhancement   : %s\n",
+                       ac97_stereo_enhancements[(cap >> 10) & 0x1f]);
+
+       val = codec->codec_read(codec, AC97_GENERAL_PURPOSE);
+       len += sprintf (page+len, "POP path         : %s 3D\n"
+                       "Sim. stereo      : %s\n"
+                       "3D enhancement   : %s\n"
+                       "Loudness         : %s\n"
+                       "Mono output      : %s\n"
+                       "MIC select       : %s\n"
+                       "ADC/DAC loopback : %s\n",
+                       val & 0x8000 ? "post" : "pre",
+                       val & 0x4000 ? "on" : "off",
+                       val & 0x2000 ? "on" : "off",
+                       val & 0x1000 ? "on" : "off",
+                       val & 0x0200 ? "MIC" : "MIX",
+                       val & 0x0100 ? "MIC2" : "MIC1",
+                       val & 0x0080 ? "on" : "off");
+
+       cap = extid;
+       len += sprintf (page+len, "Ext Capabilities :%s%s%s%s%s%s%s\n",
+                       cap & 0x0001 ? " -var rate PCM audio-" : "",
+                       cap & 0x0002 ? " -2x PCM audio out-" : "",
+                       cap & 0x0008 ? " -var rate MIC in-" : "",
+                       cap & 0x0040 ? " -PCM center DAC-" : "",
+                       cap & 0x0080 ? " -PCM surround DAC-" : "",
+                       cap & 0x0100 ? " -PCM LFE DAC-" : "",
+                       cap & 0x0200 ? " -slot/DAC mappings-" : "");
+
+       return len;
+}
+
 int ac97_probe_codec(struct ac97_codec *codec)
 {
        u16 id1, id2, cap;
@@ -381,10 +496,10 @@ int ac97_probe_codec(struct ac97_codec *codec)
        
        id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
        id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
-       for (i = 0; i < sizeof (snd_ac97_codec_ids); i++) {
-               if (snd_ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
-                       codec->name = snd_ac97_codec_ids[i].name;
-                       codec->codec_init = snd_ac97_codec_ids[i].init;
+       for (i = 0, codec->name = NULL; i < arraysize (ac97_codec_ids[i]); i++) {
+               if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
+                       codec->name = ac97_codec_ids[i].name;
+                       codec->codec_init = ac97_codec_ids[i].init;
                        break;
                }
        }
@@ -392,7 +507,6 @@ int ac97_probe_codec(struct ac97_codec *codec)
                codec->name = "Unknown";
        printk(KERN_INFO "ac97_codec: ac97 vendor id1: 0x%04x, id2: 0x%04x (%s)\n",
               id1, id2, codec->name);
-       printk(KERN_INFO "ac97_codec: capability: 0x%04x\n", cap);
 
        /* mixer masks */
        codec->supported_mixers = AC97_SUPPORTED_MASK;
@@ -437,4 +551,5 @@ static int sigmatel_init(struct ac97_codec * codec)
        return 1;
 }
 
+EXPORT_SYMBOL(ac97_read_proc);
 EXPORT_SYMBOL(ac97_probe_codec);
index 27d41f5bba2bd94c1bdb114b7ef15a694b7e6395..164dc9353569899780b5867a8b765965db828688 100644 (file)
        SOUND_MIXER_PHONEIN|SOUND_MIXER_PHONEOUT)
 
 #define AC97_RECORD_MASK (SOUND_MASK_MIC|\
-       SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\
+       SOUND_MASK_CD|SOUND_MASK_VIDEO|\
+       SOUND_MASK_LINE1| SOUND_MASK_LINE|\
        SOUND_MASK_PHONEIN)
 
 #define supported_mixer(CODEC,FOO) ( CODEC->supported_mixers & (1<<FOO) )
@@ -153,6 +154,8 @@ struct ac97_codec {
        unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
 };
 
+extern int ac97_read_proc (char *page_out, char **start, off_t off,
+                          int count, int *eof, void *data);
 extern int ac97_probe_codec(struct ac97_codec *);
 
 #endif /* _AC97_CODEC_H_ */
index 07b80515cdcc8171ebf9ec24b63f4e572e80b750..f93a799df436543272c8e9fdcd7978603562edb9 100644 (file)
@@ -61,7 +61,7 @@ dep_bool '  SYSV filesystem write support (DANGEROUS)' CONFIG_SYSV_FS_WRITE $CON
 
 tristate 'UDF filesystem support (read only)' CONFIG_UDF_FS
 if [ "$CONFIG_UDF_FS" != "n" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  dep_bool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW
+  bool '  UDF write support (DANGEROUS)' CONFIG_UDF_RW
 fi
 
 tristate 'UFS filesystem support (read only)' CONFIG_UFS_FS
index 96b3370ff4e0981a1246853256e2046db11965f6..280bf45f5a21980cf05f40a63f55a595ceb1859e 100644 (file)
@@ -334,8 +334,10 @@ adfs_notify_change(struct dentry *dentry, struct iattr *attr)
        if (error)
                goto out;
 
-       if (ia_valid & ATTR_SIZE)
+       if (ia_valid & ATTR_SIZE) {
                inode->i_size = attr->ia_size;
+               vmtruncate(inode, attr->ia_size);
+       }
        if (ia_valid & ATTR_MTIME) {
                inode->i_mtime = attr->ia_mtime;
                adfs_unix2adfs_time(inode, attr->ia_mtime);
index ed4993e36d5171fd4e5a9fa3db6e61fdbe421bf0..e0d4118612afa9c009f6f92a09b76ca64a294b60 100644 (file)
@@ -249,9 +249,8 @@ affs_notify_change(struct dentry *dentry, struct iattr *attr)
        if (attr->ia_valid & ATTR_MODE)
                inode->u.affs_i.i_protect = mode_to_prot(attr->ia_mode);
 
-       inode_setattr(inode, attr);
-       mark_inode_dirty(inode);
        error = 0;
+       inode_setattr(inode, attr);
 out:
        return error;
 }
index d49af37d1951192cc9d884ede5b8fb8cd8684ff2..abfadc6666a0fce713988e6113c173e7a7a201bd 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -62,8 +62,10 @@ void inode_setattr(struct inode * inode, struct iattr * attr)
                inode->i_uid = attr->ia_uid;
        if (ia_valid & ATTR_GID)
                inode->i_gid = attr->ia_gid;
-       if (ia_valid & ATTR_SIZE)
+       if (ia_valid & ATTR_SIZE) {
                inode->i_size = attr->ia_size;
+               vmtruncate(inode, attr->ia_size);
+       }
        if (ia_valid & ATTR_ATIME)
                inode->i_atime = attr->ia_atime;
        if (ia_valid & ATTR_MTIME)
@@ -99,7 +101,5 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
                if (!error)
                        inode_setattr(inode, attr);
        }
-       if (!error && (attr->ia_valid & ATTR_SIZE))
-               vmtruncate(inode, attr->ia_size);
        return error;
 }
index 1751829598aba47af30caccf8e1794fb3a511410..038773b9459b08fa7d6d21bd1ed385ffbf8a073d 100644 (file)
@@ -283,7 +283,7 @@ int default_fat_bmap(struct inode *inode,int sector)
                        return 0;
                return sector+sb->dir_start;
        }
-       if (sector >= MSDOS_I(inode)->mmu_private>>9)
+       if (sector >= (MSDOS_I(inode)->mmu_private+511)>>9)
                return 0;
        cluster = sector/sb->cluster_size;
        offset = sector % sb->cluster_size;
index 0037293852fc17a44f0ce27e9009415270dc434d..ee65ef82f254886dc9a82c400ec67dee57df6b94 100644 (file)
@@ -94,7 +94,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
                INIT_LIST_HEAD(&inode->i_data.pages);
                INIT_LIST_HEAD(&inode->i_dentry);
                sema_init(&inode->i_sem, 1);
-               spin_lock_init(&inode->i_shared_lock);
+               spin_lock_init(&inode->i_data.i_shared_lock);
        }
 }
 
@@ -280,7 +280,7 @@ static void dispose_list(struct list_head * head)
 
                inode = list_entry(inode_entry, struct inode, i_list);
                if (inode->i_data.nrpages)
-                       truncate_inode_pages(inode, 0);
+                       truncate_inode_pages(&inode->i_data, 0);
                clear_inode(inode);
                destroy_inode(inode);
        }
@@ -673,7 +673,7 @@ void iput(struct inode *inode)
                                        void (*delete)(struct inode *) = op->delete_inode;
                                        spin_unlock(&inode_lock);
                                        if (inode->i_data.nrpages)
-                                               truncate_inode_pages(inode, 0);
+                                               truncate_inode_pages(&inode->i_data, 0);
                                        delete(inode);
                                        spin_lock(&inode_lock);
                                }
index 802958a68b9feed041e33f5e3319cbb58cdc2190..1661a4a5c80ed85631bae645f1a31e5a59be1df3 100644 (file)
@@ -416,15 +416,16 @@ int fcntl_setlk(unsigned int fd, unsigned int cmd, struct flock *l)
        if (IS_MANDLOCK(inode) &&
            (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) {
                struct vm_area_struct *vma;
-               spin_lock(&inode->i_shared_lock);
-               for(vma = inode->i_mmap;vma;vma = vma->vm_next_share) {
+               struct address_space *mapping = inode->i_mapping;
+               spin_lock(&mapping->i_shared_lock);
+               for(vma = mapping->i_mmap;vma;vma = vma->vm_next_share) {
                        if (!(vma->vm_flags & VM_MAYSHARE))
                                continue;
-                       spin_unlock(&inode->i_shared_lock);
+                       spin_unlock(&mapping->i_shared_lock);
                        error = -EAGAIN;
                        goto out_putf;
                }
-               spin_unlock(&inode->i_shared_lock);
+               spin_unlock(&mapping->i_shared_lock);
        }
 
        error = -EINVAL;
index 5a4e790a7989c083bf7dbcc01906fdbbd919dba4..fdbf5fc822884e0eb47bfe242cb3ea448c0da68c 100644 (file)
@@ -693,6 +693,8 @@ int ncp_notify_change(struct dentry *dentry, struct iattr *attr)
                /* According to ndir, the changes only take effect after
                   closing the file */
                result = ncp_make_closed(inode);
+               if (!result)
+                       vmtruncate(inode, attr->ia_size);
        }
 out:
        return result;
index c8d42adfee2da210680bc396a81f2df3f2aefd9e..71cd43ecc10e7cbe9af6c313d492e76b2ac7b44a 100644 (file)
@@ -689,6 +689,8 @@ printk("nfs_notify_change: revalidate failed, error=%d\n", error);
        if (attr->ia_valid & ATTR_MTIME)
                inode->i_mtime = fattr.mtime.seconds;
        error = nfs_refresh_inode(inode, &fattr);
+       if (!error && (attr->ia_valid & ATTR_SIZE))
+               vmtruncate(inode, attr->ia_size);
 out:
        return error;
 }
index c071263ff52fdf88603384bd86bc8b693025fe68..0995eeeed8e6a84a8bd444a1a20c225397078f34 100644 (file)
@@ -489,7 +489,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name,
                 */
                if (attr->ia_size < inode->i_size)
                {
-                       truncate_inode_pages(inode, attr->ia_size);
+                       /* must die */
+                       truncate_inode_pages(inode->i_mapping, attr->ia_size);
                        inode->i_size = attr->ia_size;
                }
                refresh = 1;
@@ -562,6 +563,8 @@ dentry->d_parent->d_name.name, dentry->d_name.name, fattr.f_mode,attr->ia_mode);
 out:
        if (refresh)
                smb_refresh_inode(dentry);
+       if (!error && (attr->ia_valid & ATTR_SIZE))
+               vmtruncate(inode, attr->ia_size);
        return error;
 }
 
index fb8dc03ff9904b67c2ecb83a48ef24bcbe4e417f..95d6528f33a7ce306b882352740bd89ffccf1334 100644 (file)
@@ -170,11 +170,19 @@ int umsdos_notify_change_locked(struct dentry *, struct iattr *);
 int UMSDOS_notify_change (struct dentry *dentry, struct iattr *attr)
 {
        struct inode *dir = dentry->d_parent->d_inode;
+       struct inode *inode = dentry->d_inode;
        int ret;
 
+       ret = inode_change_ok (inode, attr);
+       if (ret)
+               goto out;
+
        down(&dir->i_sem);
        ret = umsdos_notify_change_locked(dentry, attr);
        up(&dir->i_sem);
+       if (ret == 0)
+               inode_setattr (inode, attr);
+out:
        return ret;
 }
 
@@ -185,20 +193,13 @@ int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
        struct dentry *demd;
-       int ret;
+       int ret = 0;
        struct file filp;
        struct umsdos_dirent entry;
 
 Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
 dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched));
 
-       ret = inode_change_ok (inode, attr);
-       if (ret) {
-printk("UMSDOS_notify_change: %s/%s change not OK, ret=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, ret);
-               goto out;
-       }
-
        if (inode->i_nlink == 0)
                goto out;
        if (inode->i_ino == UMSDOS_ROOT_INO)
@@ -276,8 +277,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, entry.nlink, ret);
 out_dput:
        dput(demd);
 out:
-       if (ret == 0)
-               inode_setattr (inode, attr);
        return ret;
 }
 
index 415f5e3fbe6f258157c3bb6e62f4adf583e5633a..08bb7b3407a48c72f1373ad7f19b82f562043e7b 100644 (file)
@@ -731,6 +731,8 @@ olddentry->d_parent->d_name.name, olddentry->d_name.name,
 oldinode->i_ino, oldinode->i_nlink));
                newattrs.ia_valid = 0;
                ret = umsdos_notify_change_locked(olddentry, &newattrs);
+               if (ret == 0)
+                       mark_inode_dirty(olddentry->d_inode);
        }
        if (olddir != dir)
                up(&olddir->i_sem);
@@ -1069,6 +1071,8 @@ link->d_parent->d_name.name, link->d_name.name, ret));
                inode->i_nlink--;
                newattrs.ia_valid = 0;
                ret = umsdos_notify_change_locked(link, &newattrs);
+               if (!ret)
+                       mark_inode_dirty(link->d_inode);
        }
 
 out_cleanup:
index b9f87286ee0ac57e2880dc9222b9662e8f6477e7..38cbb296073348e12a1fbfa1c29d114159ca41cd 100644 (file)
@@ -349,7 +349,8 @@ struct address_space {
        unsigned long           nrpages;        /* number of pages */
        struct address_space_operations *a_ops; /* methods */
        void                    *host;          /* owner: inode, block_device */
-       void                    *private;       /* private data */
+       struct vm_area_struct   *i_mmap;        /* list of mappings */
+       spinlock_t              i_shared_lock;  /* and spinlock protecting it */
 };
 
 struct block_device {
@@ -387,10 +388,8 @@ struct inode {
        struct super_block      *i_sb;
        wait_queue_head_t       i_wait;
        struct file_lock        *i_flock;
-       struct vm_area_struct   *i_mmap;
-       struct address_space    *i_mapping;     
+       struct address_space    *i_mapping;
        struct address_space    i_data; 
-       spinlock_t              i_shared_lock;
        struct dquot            *i_dquot[MAXQUOTAS];
        struct pipe_inode_info  *i_pipe;
        struct block_device     *i_bdev;
index cfb5f97ecaf759210d2b6db30250e1982ad65db2..c2b26f1b71dbe28a06d49962656c07488b63aac9 100644 (file)
@@ -436,7 +436,7 @@ struct zone_t;
 extern void remove_inode_page(struct page *);
 extern unsigned long page_unuse(struct page *);
 extern int shrink_mmap(int, int, zone_t *);
-extern void truncate_inode_pages(struct inode *, loff_t);
+extern void truncate_inode_pages(struct address_space *, loff_t);
 
 /* generic vm_area_ops exported for stackable file systems */
 extern int filemap_swapout(struct page * page, struct file *file);
index de0b59bac65dde543404f5901fa7dc2866b38b9d..71989b3f734245969e161aae08c8cf8cbcdf9c8d 100644 (file)
@@ -252,18 +252,19 @@ static inline int dup_mmap(struct mm_struct * mm)
                tmp->vm_next = NULL;
                file = tmp->vm_file;
                if (file) {
+                       struct inode *inode = file->f_dentry->d_inode;
                        get_file(file);
                        if (tmp->vm_flags & VM_DENYWRITE)
-                               atomic_dec(&file->f_dentry->d_inode->i_writecount);
+                               atomic_dec(&inode->i_writecount);
       
                        /* insert tmp into the share list, just after mpnt */
-                       spin_lock(&file->f_dentry->d_inode->i_shared_lock);
+                       spin_lock(&inode->i_mapping->i_shared_lock);
                        if((tmp->vm_next_share = mpnt->vm_next_share) != NULL)
                                mpnt->vm_next_share->vm_pprev_share =
                                        &tmp->vm_next_share;
                        mpnt->vm_next_share = tmp;
                        tmp->vm_pprev_share = &mpnt->vm_next_share;
-                       spin_unlock(&file->f_dentry->d_inode->i_shared_lock);
+                       spin_unlock(&inode->i_mapping->i_shared_lock);
                }
 
                /* Copy the pages, but defer checking for errors */
index 4772ed2544f8ae14f1d5ac25a77376e2c7f01ca7..eac9633352a6daf42e7511ab321789ed598117a6 100644 (file)
@@ -124,7 +124,7 @@ void invalidate_inode_pages(struct inode * inode)
  * Truncate the page cache at a set offset, removing the pages
  * that are beyond that offset (and zeroing out partial pages).
  */
-void truncate_inode_pages(struct inode * inode, loff_t lstart)
+void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
 {
        struct list_head *head, *curr;
        struct page * page;
@@ -134,7 +134,7 @@ void truncate_inode_pages(struct inode * inode, loff_t lstart)
        start = (lstart + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 
 repeat:
-       head = &inode->i_mapping->pages;
+       head = &mapping->pages;
        spin_lock(&pagecache_lock);
        curr = head->next;
        while (curr != head) {
index 6abcf9bb0d1cca573f5ff3b24a39903a2c37d2c4..6bf219e8cd6d5be54696a8f9da69bb649568f285 100644 (file)
@@ -860,16 +860,17 @@ void vmtruncate(struct inode * inode, loff_t offset)
 {
        unsigned long partial, pgoff;
        struct vm_area_struct * mpnt;
+       struct address_space *mapping = inode->i_mapping;
 
-       truncate_inode_pages(inode, offset);
-       spin_lock(&inode->i_shared_lock);
-       if (!inode->i_mmap)
+       truncate_inode_pages(mapping, offset);
+       spin_lock(&mapping->i_shared_lock);
+       if (!mapping->i_mmap)
                goto out_unlock;
 
        pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1);
 
-       mpnt = inode->i_mmap;
+       mpnt = mapping->i_mmap;
        do {
                struct mm_struct *mm = mpnt->vm_mm;
                unsigned long start = mpnt->vm_start;
@@ -903,7 +904,7 @@ void vmtruncate(struct inode * inode, loff_t offset)
                flush_tlb_range(mm, start, end);
        } while ((mpnt = mpnt->vm_next_share) != NULL);
 out_unlock:
-       spin_unlock(&inode->i_shared_lock);
+       spin_unlock(&mapping->i_shared_lock);
        if (inode->i_op && inode->i_op->truncate)
                inode->i_op->truncate(inode);
 }
index aca4d99d8bb40142dba9245f50bbe211021ac187..cab60332ae79331519b9b074f6cb93818647c78a 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -75,13 +75,14 @@ static inline void remove_shared_vm_struct(struct vm_area_struct *vma)
        struct file * file = vma->vm_file;
 
        if (file) {
+               struct inode *inode = file->f_dentry->d_inode;
                if (vma->vm_flags & VM_DENYWRITE)
-                       atomic_inc(&file->f_dentry->d_inode->i_writecount);
-               spin_lock(&file->f_dentry->d_inode->i_shared_lock);
+                       atomic_inc(&inode->i_writecount);
+               spin_lock(&inode->i_mapping->i_shared_lock);
                if(vma->vm_next_share)
                        vma->vm_next_share->vm_pprev_share = vma->vm_pprev_share;
                *vma->vm_pprev_share = vma->vm_next_share;
-               spin_unlock(&file->f_dentry->d_inode->i_shared_lock);
+               spin_unlock(&inode->i_mapping->i_shared_lock);
        }
 }
 
@@ -887,16 +888,17 @@ void insert_vm_struct(struct mm_struct *mm, struct vm_area_struct *vmp)
        file = vmp->vm_file;
        if (file) {
                struct inode * inode = file->f_dentry->d_inode;
+               struct address_space *mapping = inode->i_mapping;
                if (vmp->vm_flags & VM_DENYWRITE)
                        atomic_dec(&inode->i_writecount);
       
                /* insert vmp into inode's share list */
-               spin_lock(&inode->i_shared_lock);
-               if((vmp->vm_next_share = inode->i_mmap) != NULL)
-                       inode->i_mmap->vm_pprev_share = &vmp->vm_next_share;
-               inode->i_mmap = vmp;
-               vmp->vm_pprev_share = &inode->i_mmap;
-               spin_unlock(&inode->i_shared_lock);
+               spin_lock(&mapping->i_shared_lock);
+               if((vmp->vm_next_share = mapping->i_mmap) != NULL)
+                       mapping->i_mmap->vm_pprev_share = &vmp->vm_next_share;
+               mapping->i_mmap = vmp;
+               vmp->vm_pprev_share = &mapping->i_mmap;
+               spin_unlock(&mapping->i_shared_lock);
        }
 }
 
index d1d89b1e4bebce9a5ddcdc578d25e51ffe48aefb..94345259d7ce4a88ae9f34de89b40a402b4d9d0f 100644 (file)
@@ -426,12 +426,8 @@ int irda_device_setup(struct net_device *dev)
        memset(dev->broadcast, 0xff, 4);
 
        dev->mtu = 2048;
-       dev->tbusy = 1;
-       
        dev_init_buffers(dev);
-
        dev->flags = IFF_NOARP;
-       
        return 0;
 }
 
index 355bae95575db6d684efb5da065ab281699e5229..a9baa70f8b0287a0df6264a0cdaa0d93e4b169c7 100644 (file)
@@ -126,7 +126,7 @@ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
         * is up, that means that the "user" really wants to connect. If not
         * we notify the user about the possibility of an IrLAN connection
         */
-       if (self->dev.start) {
+       if (test_bit(LINK_STATE_START, &self->dev.state)) {
                /* Open TSAPs */
                irlan_client_open_ctrl_tsap(self);
                irlan_open_data_tsap(self);
index 9d276e0a1296b751d5969e2f850c3f0ef9b13e6d..e7c20e25ad7633adf053b5959ebe93cb3349115c 100644 (file)
@@ -120,7 +120,7 @@ void irlan_watchdog_timer_expired(void *data)
        ASSERT(self->magic == IRLAN_MAGIC, return;);
 
        /* Check if device still configured */
-       if (self->dev.start) {
+       if (test_bit(LINK_STATE_START, &self->dev.state)) {
                IRDA_DEBUG(0, __FUNCTION__ 
                      "(), notifying irmanager to stop irlan!\n");
                mgr_event.event = EVENT_IRLAN_STOP;
@@ -363,7 +363,7 @@ void irlan_close(struct irlan_cb *self)
        ASSERT(self->magic == IRLAN_MAGIC, return;);
 
        /* Check if device is still configured */
-       if (self->dev.start) {
+       if (test_bit(LINK_STATE_START, &self->dev.state)) {
                IRDA_DEBUG(0, __FUNCTION__ 
                       "(), Device still configured, closing later!\n");
 
@@ -420,7 +420,7 @@ void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
                irlan_open_unicast_addr(self);
        }
        /* Ready to transfer Ethernet frames (at last) */
-       self->dev.tbusy = 0;
+       netif_start_queue(&self->dev);
 }
 
 void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
@@ -454,8 +454,7 @@ void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos,
        irlan_set_multicast_filter(self, TRUE);
 
        /* Ready to transfer Ethernet frames */
-       self->dev.tbusy = 0;
-
+       netif_start_queue(&self->dev);
        irlan_eth_send_gratuitous_arp(&self->dev);
 }
 
@@ -1196,7 +1195,7 @@ static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
                                                  buf+len);
                        
                        len += sprintf(buf+len, "tx busy: %s\n", 
-                                      self->dev.tbusy ? "TRUE" : "FALSE");
+                                      test_bit(LINK_STATE_XOFF, &self->dev.state) ? "TRUE" : "FALSE");
                        
                        len += sprintf(buf+len, "\n");
                }
index c2037ad74e7ed6eb126972dddba410081ca1f86e..5ee81ec0341763988886f2fab5230bf1bda8e5a5 100644 (file)
@@ -62,8 +62,6 @@ int irlan_eth_init(struct net_device *dev)
        dev->get_stats          = irlan_eth_get_stats;
        dev->set_multicast_list = irlan_eth_set_multicast_list;
 
-       dev->tbusy = 1;
-       
        ether_setup(dev);
        
        /* 
@@ -124,9 +122,7 @@ int irlan_eth_open(struct net_device *dev)
        ASSERT(self != NULL, return -1;);
 
        /* Ready to play! */
-/*     dev->tbusy = 0; */ /* Wait until data link is ready */
-       dev->interrupt = 0;
-       dev->start = 1;
+/*     netif_start_queue(dev) */ /* Wait until data link is ready */
 
        self->notify_irmanager = TRUE;
 
@@ -153,9 +149,8 @@ int irlan_eth_close(struct net_device *dev)
        IRDA_DEBUG(2, __FUNCTION__ "()\n");
        
        /* Stop device */
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
+       
        irlan_mod_dec_use_count();
 
        irlan_close_data_channel(self);
@@ -192,10 +187,6 @@ int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
        ASSERT(self != NULL, return 0;);
        ASSERT(self->magic == IRLAN_MAGIC, return 0;);
 
-       /* Check if IrTTP can accept more frames */
-       if (dev->tbusy)
-               return -EBUSY;
-       
        /* skb headroom large enough to contain all IrDA-headers? */
        if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
                struct sk_buff *new_skb = 
@@ -279,7 +270,7 @@ int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
  * Function irlan_eth_flow (status)
  *
  *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by 
- *    controlling the dev->tbusy variable.
+ *    controlling the queue stop/start.
  */
 void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
 {
@@ -297,15 +288,13 @@ void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
        
        switch (flow) {
        case FLOW_STOP:
-               dev->tbusy = 1;
+               netif_stop_queue(dev);
                break;
        case FLOW_START:
        default:
                /* Tell upper layers that its time to transmit frames again */
-               dev->tbusy = 0;
-
                /* Schedule network layer */
-               mark_bh(NET_BH);                
+               netif_start_queue(dev);
                break;
        }
 }
index 0e93f6d2666097a4be91b3f8d15b3f33be111046..3e2b3425218b1c5d4754026af04724701a44d4a2 100644 (file)
@@ -62,7 +62,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                stats->rx_errors++;
                return 0;
        }
@@ -181,60 +181,25 @@ static int nr_set_mac_address(struct net_device *dev, void *addr)
 
 static int nr_open(struct net_device *dev)
 {
-       dev->tbusy = 0;
-       dev->start = 1;
-
        MOD_INC_USE_COUNT;
-
+       netif_start_queue(dev);
        ax25_listen_register((ax25_address *)dev->dev_addr, NULL);
-
        return 0;
 }
 
 static int nr_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
-
+       netif_stop_queue(dev);
        ax25_listen_release((ax25_address *)dev->dev_addr, NULL);
-
        MOD_DEC_USE_COUNT;
-
        return 0;
 }
 
 static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
-
-       if (skb == NULL || dev == NULL)
-               return 0;
-
-       if (!dev->start) {
-               printk(KERN_ERR "NET/ROM: nr_xmit - called when iface is down\n");
-               return 1;
-       }
-
-       cli();
-
-       if (dev->tbusy != 0) {
-               sti();
-               stats->tx_errors++;
-               return 1;
-       }
-
-       dev->tbusy = 1;
-
-       sti();
-
-       kfree_skb(skb);
-
+       dev_kfree_skb(skb);
        stats->tx_errors++;
-
-       dev->tbusy = 0;
-
-       mark_bh(NET_BH);
-
        return 0;
 }
 
@@ -246,7 +211,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev)
 int nr_init(struct net_device *dev)
 {
        dev->mtu                = NR_MAX_PACKET_SIZE;
-       dev->tbusy              = 0;
        dev->hard_start_xmit    = nr_xmit;
        dev->open               = nr_open;
        dev->stop               = nr_close;
index ed3599a934f0845efb881bc34bae33791ff8224d..19065f6786804fd8c81095b06a92043d2808ee92 100644 (file)
@@ -57,7 +57,7 @@ int rose_rx_ip(struct sk_buff *skb, struct net_device *dev)
        struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
 #ifdef CONFIG_INET
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                stats->rx_errors++;
                return 0;
        }
@@ -145,25 +145,17 @@ static int rose_set_mac_address(struct net_device *dev, void *addr)
 
 static int rose_open(struct net_device *dev)
 {
-       dev->tbusy = 0;
-       dev->start = 1;
-
        MOD_INC_USE_COUNT;
-
+       netif_start_queue(dev);
        rose_add_loopback_node((rose_address *)dev->dev_addr);
-
        return 0;
 }
 
 static int rose_close(struct net_device *dev)
 {
-       dev->tbusy = 1;
-       dev->start = 0;
-
-       MOD_DEC_USE_COUNT;
-
+       netif_stop_queue(dev);
        rose_del_loopback_node((rose_address *)dev->dev_addr);
-
+       MOD_DEC_USE_COUNT;
        return 0;
 }
 
@@ -171,34 +163,12 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
-       if (skb == NULL || dev == NULL)
-               return 0;
-
-       if (!dev->start) {
+       if (!test_bit(LINK_STATE_START, &dev->state)) {
                printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
                return 1;
        }
-
-       cli();
-
-       if (dev->tbusy != 0) {
-               sti();
-               stats->tx_errors++;
-               return 1;
-       }
-
-       dev->tbusy = 1;
-
-       sti();
-
-       kfree_skb(skb);
-
+       dev_kfree_skb(skb);
        stats->tx_errors++;
-
-       dev->tbusy = 0;
-
-       mark_bh(NET_BH);
-
        return 0;
 }
 
@@ -210,7 +180,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev)
 int rose_init(struct net_device *dev)
 {
        dev->mtu                = ROSE_MAX_PACKET_SIZE - 2;
-       dev->tbusy              = 0;
        dev->hard_start_xmit    = rose_xmit;
        dev->open               = rose_open;
        dev->stop               = rose_close;
index af7191563064a437e1896537fea0b498cd20d8ae..ffa93eed3ac87e0f3b304b6fb8abd1b87c75b6bb 100644 (file)
@@ -526,7 +526,10 @@ static int device_shutdown (wan_device_t* wandev)
        for (dev = wandev->dev; dev;)
        {
                if (delete_interface(wandev, dev->name, 0))
-                       dev = dev->slave;
+               {
+                       struct net_device **slave = dev->priv;
+                       dev = *slave;
+               }
        }
        if (wandev->ndev)
                return -EBUSY;  /* there are opened interfaces  */
@@ -608,8 +611,10 @@ static int device_new_if (wan_device_t* wandev, wanif_conf_t* u_conf)
 #endif                         
                        err = register_netdev(dev);
                        if (!err) {
+                               struct net_device **slave = dev->priv;
+
                                cli();  /***** critical section start *****/
-                               dev->slave = wandev->dev;
+                               *slave = wandev->dev;
                                wandev->dev = dev;
                                ++wandev->ndev;
                                sti();  /****** critical section end ******/
@@ -684,14 +689,19 @@ static int delete_interface (wan_device_t *wandev, char *name, int force)
 {
        struct net_device *dev, *prev;
 
-       for (dev = wandev->dev, prev = NULL;
-               dev && strcmp(name, dev->name);
-               prev = dev, dev = dev->slave);
+       dev = wandev->dev;
+       prev = NULL;
+       while (dev && strcmp(name, dev->name)) {
+               struct net_device **slave = dev->priv;
+
+               prev = dev;
+               dev = *slave;
+       }
 
        if (dev == NULL)
                return -ENODEV; /* interface not found */
 
-       if (dev->start) {
+       if (test_bit(LINK_STATE_START, &dev->state)) {
                if (force) {
                        printk(KERN_WARNING
                                "%s: deleting opened interface %s!\n",
@@ -705,10 +715,16 @@ static int delete_interface (wan_device_t *wandev, char *name, int force)
                wandev->del_if(wandev, dev);
 
        cli();                  /***** critical section start *****/
-       if (prev)
-               prev->slave = dev->slave;
-       else
-               wandev->dev = dev->slave;
+       if (prev) {
+               struct net_device **prev_slave = prev->priv;
+               struct net_device **slave = dev->priv;
+
+               *prev_slave = *slave;
+       } else {
+               struct net_device **slave = dev->priv;
+
+               wandev->dev = *slave;
+       }
        --wandev->ndev;
        sti();                  /****** critical section end ******/