]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.2.0 (pre1) (28 Dec 1998) 2.2.0pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:46 +0000 (15:17 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:46 +0000 (15:17 -0500)
 we're in the pre-2.2.0 series now, I'm all synched up with Alan, and I
don't have anything pending any more. Over the internet nobody can hear
you all scream in pain over all your favourite features that didn't make
it.

Linus "another year older and wise as hell by now" Torvalds

35 files changed:
Makefile
arch/arm/kernel/ecard.c
arch/i386/kernel/io_apic.c
arch/i386/kernel/smp.c
arch/i386/kernel/time.c
drivers/block/ll_rw_blk.c
drivers/char/pc_keyb.c
drivers/net/8390.c
drivers/net/8390.h
drivers/net/cosa.c
drivers/net/cosa.h
drivers/net/lance.c
drivers/net/sdlamain.c
drivers/net/via-rhine.c
drivers/scsi/ppa.c
drivers/sound/es1371.c
drivers/sound/mad16.c
drivers/sound/opl3sa.c
drivers/sound/sb.h
drivers/sound/sb_common.c
drivers/sound/sb_mixer.c
drivers/sound/sb_mixer.h
fs/autofs/waitq.c
fs/dcache.c
fs/fat/inode.c
fs/nfs/dir.c
fs/nfs/inode.c
include/asm-i386/system.h
include/asm-i386/timex.h
include/linux/genhd.h
kernel/sched.c
mm/page_io.c
net/ipx/af_ipx.c
net/netrom/nr_dev.c
net/wanrouter/wanmain.c

index b244ba9e0ea7eb8d4af0055e4fe1bc08375242d3..53ff0e7ad92c559545235a247f1ef77843fca9fd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,7 @@
 VERSION = 2
-PATCHLEVEL = 1
-SUBLEVEL = 133
+PATCHLEVEL = 2
+SUBLEVEL = 0
+EXTRAVERSION =-pre1
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -58,6 +59,8 @@ endif
 
 ROOT_DEV = CURRENT
 
+KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
+
 #
 # INSTALL_PATH specifies where to place the updated kernel and system map
 # images.  Uncomment if you want to place them anywhere other than root.
@@ -278,7 +281,7 @@ include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
        @mv -f .ver $@
 
 include/linux/version.h: ./Makefile
-       @echo \#define UTS_RELEASE \"$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)\" > .ver
+       @echo \#define UTS_RELEASE \"$(KERNELRELEASE)\" > .ver
        @echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)` >> .ver
        @echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))' >>.ver
        @mv -f .ver $@
@@ -305,7 +308,7 @@ $(patsubst %, _mod_%, $(SUBDIRS)) : include/linux/version.h
 
 modules_install:
        @( \
-       MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(VERSION).$(PATCHLEVEL).$(SUBLEVEL); \
+       MODLIB=$(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE); \
        cd modules; \
        MODULES=""; \
        inst_mod() { These="`cat $$1`"; MODULES="$$MODULES $$These"; \
index fc092a495eff0300f08e0e9bd83c95f55732543e..fe1c75f5c8dbcf45eca823710d9b6ded37cdb439 100644 (file)
@@ -215,7 +215,7 @@ static void ecard_irq_noexpmask(int intr_no, void *dev_id, struct pt_regs *regs)
                } else
                        lockup = 0;
 
-               if (!last || time_after(jiffies, last + 500)) {
+               if (!last || time_after(jiffies, last + 5*HZ)) {
                        last = jiffies;
                        printk(KERN_ERR "\nUnrecognised interrupt from backplane\n");
                }
index 6e653e9272fa2bd726c5a222d8e2a1dc40eb5a9c..232abf78d405c8afaed0b030eb88af2d025c464e 100644 (file)
@@ -682,7 +682,8 @@ void __init print_IO_APIC(void)
        printk(".... register #01: %08X\n", *(int *)&reg_01);
        printk(".......     : max redirection entries: %04X\n", reg_01.entries);
        if (    (reg_01.entries != 0x0f) && /* ISA-only Neptune boards */
-               (reg_01.entries != 0x17)    /* ISA+PCI boards */
+               (reg_01.entries != 0x17) && /* ISA+PCI boards */
+               (reg_01.entries != 0x3F)    /* Xeon boards */
        )
                UNEXPECTED_IO_APIC();
        if (reg_01.entries == 0x0f)
@@ -690,7 +691,8 @@ void __init print_IO_APIC(void)
 
        printk(".......     : IO APIC version: %04X\n", reg_01.version);
        if (    (reg_01.version != 0x10) && /* oldest IO-APICs */
-               (reg_01.version != 0x11)  /* my IO-APIC */
+               (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */
+               (reg_01.version != 0x13)    /* Xeon IO-APICs */
        )
                UNEXPECTED_IO_APIC();
        if (reg_01.__reserved_1 || reg_01.__reserved_2)
index b6a779dfe3e04668d523677d4f9ec1fc7db4cf3f..d9fcc1e5c155afe843029aff41b21a633d6e1b80 100644 (file)
@@ -140,7 +140,6 @@ unsigned long mp_ioapic_addr = 0xFEC00000;          /* Address of the I/O apic (not yet
 unsigned char boot_cpu_id = 0;                         /* Processor that is doing the boot up                  */
 static int smp_activated = 0;                          /* Tripped once we need to start cross invalidating     */
 int apic_version[NR_CPUS];                             /* APIC version number                                  */
-volatile int smp_commenced=0;                  /* Tripped when we start scheduling                     */
 unsigned long apic_retval;                             /* Just debugging the assembler..                       */
 
 volatile unsigned long kernel_counter=0;               /* Number of times the processor holds the lock         */
@@ -633,13 +632,17 @@ void __init smp_store_cpu_info(int id)
  *     we use to track CPUs as they power up.
  */
 
+static atomic_t smp_commenced = ATOMIC_INIT(0);
+
 void __init smp_commence(void)
 {
        /*
         *      Lets the callins below out of their loop.
         */
        SMP_PRINTK(("Setting commenced=1, go go go\n"));
-       smp_commenced=1;
+
+       wmb();
+       atomic_set(&smp_commenced,1);
 }
 
 void __init enable_local_APIC(void)
@@ -740,8 +743,8 @@ int __init start_secondary(void *unused)
        mtrr_init_secondary_cpu ();
 #endif
        smp_callin();
-       while (!smp_commenced)
-               barrier();
+       while (!atomic_read(&smp_commenced))
+               /* nothing */ ;
        return cpu_idle(NULL);
 }
 
@@ -972,6 +975,27 @@ static void __init do_boot_cpu(int i)
        *((volatile unsigned long *)phys_to_virt(8192)) = 0;
 }
 
+cycles_t cacheflush_time;
+extern unsigned long cpu_hz;
+
+static void smp_tune_scheduling (void)
+{
+       /*
+        * Rough estimation for SMP scheduling, this is the number of
+        * cycles it takes for a fully memory-limited process to flush
+        * the SMP-local cache.
+        *
+        * (For a P5 this pretty much means we will choose another idle
+        *  CPU almost always at wakeup time (this is due to the small
+        *  L1 cache), on PIIs it's around 50-100 usecs, depending on
+        *  the cache size)
+        */
+       cacheflush_time = cpu_hz/1024*boot_cpu_data.x86_cache_size/5000;
+       printk("per-CPU timeslice cutoff: %ld.%ld usecs.\n",
+               (long)cacheflush_time/(cpu_hz/1000000),
+               ((long)cacheflush_time*100/(cpu_hz/1000000)) % 100);
+}
+
 unsigned int prof_multiplier[NR_CPUS];
 unsigned int prof_counter[NR_CPUS];
 
@@ -1004,6 +1028,7 @@ void __init smp_boot_cpus(void)
         */
 
        smp_store_cpu_info(boot_cpu_id);                        /* Final full version of the data */
+       smp_tune_scheduling();
        printk("CPU%d: ", boot_cpu_id);
        print_cpu_info(&cpu_data[boot_cpu_id]);
 
index 28a57ead740d21f2cf1abd335d1544a2aefb2bad..2d89fcbe8d81eb78db8bc4e9bcbc2941fbaf6039 100644 (file)
@@ -72,8 +72,6 @@ extern int setup_x86_irq(int, struct irqaction *);
 
 unsigned long cpu_hz;  /* Detected as we calibrate the TSC */
 
-cycles_t cacheflush_time;
-
 /* Number of usecs that the last interrupt was delayed */
 static int delay_at_last_interrupt;
 
@@ -88,7 +86,7 @@ static unsigned long fast_gettimeoffset_quotient=0;
 
 extern rwlock_t xtime_lock;
 
-static unsigned long do_fast_gettimeoffset(void)
+static inline unsigned long do_fast_gettimeoffset(void)
 {
        register unsigned long eax asm("ax");
        register unsigned long edx asm("dx");
@@ -118,6 +116,13 @@ static unsigned long do_fast_gettimeoffset(void)
        return delay_at_last_interrupt + edx;
 }
 
+#define TICK_SIZE tick
+
+/*
+ * Older CPU's don't have the rdtsc instruction..
+ */
+#if CPU < 586
+
 /* This function must be called with interrupts disabled 
  * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
  * 
@@ -150,8 +155,6 @@ static unsigned long do_fast_gettimeoffset(void)
  * comp.protocols.time.ntp!
  */
 
-#define TICK_SIZE tick
-
 static unsigned long do_slow_gettimeoffset(void)
 {
        int count;
@@ -233,6 +236,12 @@ static unsigned long do_slow_gettimeoffset(void)
 
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
 
+#else
+
+#define do_gettimeoffset()     do_fast_gettimeoffset()
+
+#endif
+
 /*
  * This version of gettimeofday has microsecond resolution
  * and better than microsecond precision on fast x86 machines with TSC.
@@ -625,7 +634,9 @@ __initfunc(void time_init(void))
  * smart.  See arch/i386/kernel/apm.c.
  */
        if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) {
+#ifndef do_gettimeoffset
                do_gettimeoffset = do_fast_gettimeoffset;
+#endif
                do_get_fast_time = do_gettimeofday;
                use_tsc = 1;
                fast_gettimeoffset_quotient = calibrate_tsc();
@@ -642,13 +653,5 @@ __initfunc(void time_init(void))
                        printk("Detected %ld Hz processor.\n", cpu_hz);
                }
        }
-
-       /*
-        * Rough estimation for SMP scheduling, this is the number of
-        * cycles it takes for a fully memory-limited process to flush
-        * the SMP-local cache.
-        */
-       cacheflush_time = cpu_hz/10000;
-
        setup_x86_irq(0, &irq0);
 }
index 3ef4f81c38f790b7351bba2d368a06fa011245f0..086956325d2ef8c073c58f28bf30cca6e61c7ce6 100644 (file)
@@ -644,6 +644,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[])
                if (bh[i]) {
                        clear_bit(BH_Dirty, &bh[i]->b_state);
                        clear_bit(BH_Uptodate, &bh[i]->b_state);
+                       bh[i]->b_end_io(bh[i], 0);
                }
        }
        return;
index 2b0d8f3a7737b735d7fef30a24c7cc37adab4dde..13bfbe894d447ec80c0baef4b062ea4376cb536b 100644 (file)
@@ -761,6 +761,11 @@ static int fasync_aux(int fd, struct file *filp, int on)
 }
 
 
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
 static int release_aux(struct inode * inode, struct file * file)
 {
        fasync_aux(-1, file, 0);
@@ -768,11 +773,7 @@ static int release_aux(struct inode * inode, struct file * file)
                return 0;
        kbd_write_cmd(AUX_INTS_OFF);                        /* Disable controller ints */
        kbd_write(KBD_CCMD_MOUSE_DISABLE, KBD_CNTL_REG);
-#ifdef CONFIG_MCA
-       free_irq(AUX_IRQ, inode);
-#else
-       free_irq(AUX_IRQ, NULL);
-#endif
+       free_irq(AUX_IRQ, AUX_DEV);
        return 0;
 }
 
@@ -787,11 +788,7 @@ static int open_aux(struct inode * inode, struct file * file)
                return 0;
        }
        queue->head = queue->tail = 0;          /* Flush input queue */
-#ifdef CONFIG_MCA
-       if (request_irq(AUX_IRQ, keyboard_interrupt, MCA_bus ? SA_SHIRQ : 0, "PS/2 Mouse", inode)) {
-#else
-       if (request_irq(AUX_IRQ, keyboard_interrupt, 0, "PS/2 Mouse", NULL)) {
-#endif
+       if (request_irq(AUX_IRQ, keyboard_interrupt, SA_SHIRQ, "PS/2 Mouse", AUX_DEV)) {
                aux_count--;
                return -EBUSY;
        }
index cd638f3df1d082de5df995fa1b0d31f0e597e2c0..54045db1eb27669e959949143a97e6191f91ea8d 100644 (file)
@@ -37,7 +37,7 @@
                          68K Macintosh. Support >16bit I/O spaces
   Paul Gortmaker       : add kmod support for auto-loading of the 8390
                          module by all drivers that require it.
-
+  Alan Cox             : Spinlocking work, added 'BUG_83C690'
 
   Sources:
   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
@@ -72,6 +72,8 @@ static const char *version =
 #define NS8390_CORE
 #include "8390.h"
 
+#define BUG_83C690
+
 /* These are the operational function interfaces to board-specific
    routines.
        void reset_8390(struct device *dev)
@@ -110,6 +112,34 @@ static void ei_rx_overrun(struct device *dev);
 static void NS8390_trigger_send(struct device *dev, unsigned int length,
                                                                int start_page);
 static void set_multicast_list(struct device *dev);
+static void do_set_multicast_list(struct device *dev);
+
+/*
+ *     SMP and the 8390 setup.
+ *
+ *     The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ *     a page register that controls bank and packet buffer access. We guard
+ *     this with ei_local->page_lock. Nobody should assume or set the page other
+ *     than zero when the lock is not held. Lock holders must restore page 0
+ *     before unlocking. Even pure readers must take the lock to protect in 
+ *     page 0.
+ *
+ *     To make life difficult the chip can also be very slow. We therefore can't
+ *     just use spinlocks. For the longer lockups we disable the irq the device
+ *     sits on and hold the lock. We must hold the lock because there is a dual
+ *     processor case other than interrupts (get stats/set multicast list in
+ *     parallel with each other and transmit).
+ *
+ *     Note: in theory we can just disable the irq on the card _but_ there is
+ *     a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
+ *     enter lock, take the queued irq. So we waddle instead of flying.
+ *
+ *     Finally by special arrangement for the purpose of being generally 
+ *     annoying the transmit function is called bh atomic. That places
+ *     restrictions on the user context callers as disable_irq won't save
+ *     them.
+ */
 
 \f
 /* Open/initialize the board.  This routine goes all-out, setting everything
@@ -118,6 +148,7 @@ static void set_multicast_list(struct device *dev);
    */
 int ei_open(struct device *dev)
 {
+       unsigned long flags;
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
 
        /* This can't happen unless somebody forgot to call ethdev_init(). */
@@ -127,7 +158,14 @@ int ei_open(struct device *dev)
                return -ENXIO;
        }
     
+       /*
+        *      Grab the page lock so we own the register set, then call
+        *      the init function.
+        */
+      
+       spin_lock_irqsave(&ei_local->page_lock, flags);
        NS8390_init(dev, 1);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
        dev->start = 1;
        ei_local->irqlock = 0;
        return 0;
@@ -136,7 +174,16 @@ int ei_open(struct device *dev)
 /* Opposite of above. Only used when "ifconfig <devname> down" is done. */
 int ei_close(struct device *dev)
 {
+       struct ei_device *ei_local = (struct ei_device *) dev->priv;
+       unsigned long flags;
+
+       /*
+        *      Hold the page lock during close
+        */
+               
+       spin_lock_irqsave(&ei_local->page_lock, flags);
        NS8390_init(dev, 0);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
        dev->start = 0;
        return 0;
 }
@@ -146,24 +193,39 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
        int e8390_base = dev->base_addr;
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
        int length, send_length, output_page;
+       unsigned long flags;
 
        /*
         *  We normally shouldn't be called if dev->tbusy is set, but the
         *  existing code does anyway. If it has been too long since the
-        *  last Tx, we assume the board has died and kick it.
+        *  last Tx, we assume the board has died and kick it. We are
+        *  bh_atomic here.
         */
  
        if (dev->tbusy) 
        {       /* Do timeouts, just like the 8003 driver. */
-               int txsr = inb(e8390_base+EN0_TSR), isr;
+               int txsr;
+               int isr;
                int tickssofar = jiffies - dev->trans_start;
+
+               /*
+                *      Need the page lock. Now see what went wrong. This bit is
+                *      fast.
+                */
+                               
+               spin_lock_irqsave(&ei_local->page_lock, flags);
+               txsr = inb(e8390_base+EN0_TSR);
                if (tickssofar < TX_TIMEOUT ||  (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) 
+               {
+                       spin_unlock_irqrestore(&ei_local->page_lock, flags);
                        return 1;
+               }
 
                ei_local->stat.tx_errors++;
                isr = inb(e8390_base+EN0_ISR);
                if (dev->start == 0) 
                {
+                       spin_unlock_irqrestore(&ei_local->page_lock, flags);
                        printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name);
                        return 1;
                }
@@ -184,22 +246,54 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
                        ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
                }
 
+               /*
+                *      Play shuffle the locks, a reset on some chips takes a few
+                *      mS. We very rarely hit this point.
+                */
+                
+               spin_unlock_irqrestore(&ei_local->page_lock, flags);
+
+               /* Ugly but a reset can be slow, yet must be protected */
+               
+               disable_irq(dev->irq);
+               synchronize_irq();
+               spin_lock(&ei_local->page_lock);
+               
                /* Try to restart the card.  Perhaps the user has fixed something. */
                ei_reset_8390(dev);
                NS8390_init(dev, 1);
+               
+               spin_unlock(&ei_local->page_lock);
+               enable_irq(dev->irq);
                dev->trans_start = jiffies;
        }
     
        length = skb->len;
 
-       /* Mask interrupts from the ethercard. */
+       /* Mask interrupts from the ethercard. 
+          SMP: We have to grab the lock here otherwise the IRQ handler
+          on another CPU can flip window and race the IRQ mask set. We end
+          up trashing the mcast filter not disabling irqs if we dont lock */
+          
+       spin_lock_irqsave(&ei_local->page_lock, flags);
        outb_p(0x00, e8390_base + EN0_IMR);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+       
+       
+       /*
+        *      Slow phase with lock held.
+        */
+        
        disable_irq(dev->irq);
        synchronize_irq();
+       
+       spin_lock(&ei_local->page_lock);
+       
        if (dev->interrupt) 
        {
                printk(KERN_WARNING "%s: Tx request while isr active.\n",dev->name);
                outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+               spin_unlock(&ei_local->page_lock);
                enable_irq(dev->irq);
                ei_local->stat.tx_errors++;
                dev_kfree_skb(skb);
@@ -243,6 +337,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
                ei_local->irqlock = 0;
                dev->tbusy = 1;
                outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+               spin_unlock(&ei_local->page_lock);
                enable_irq(dev->irq);
                ei_local->stat.tx_errors++;
                return 1;
@@ -294,6 +389,8 @@ static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
        /* Turn 8390 interrupts back on. */
        ei_local->irqlock = 0;
        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
+       
+       spin_unlock(&ei_local->page_lock);
        enable_irq(dev->irq);
 
        dev_kfree_skb (skb);
@@ -320,6 +417,13 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
     
        e8390_base = dev->base_addr;
        ei_local = (struct ei_device *) dev->priv;
+
+       /*
+        *      Protect the irq test too.
+        */
+        
+       spin_lock(&ei_local->page_lock);
+
        if (dev->interrupt || ei_local->irqlock) 
        {
 #if 1 /* This might just be an interrupt for a PCI device sharing this line */
@@ -330,15 +434,17 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                           dev->name, inb_p(e8390_base + EN0_ISR),
                           inb_p(e8390_base + EN0_IMR));
 #endif
+               spin_unlock(&ei_local->page_lock);
                return;
        }
     
+       
        dev->interrupt = 1;
     
        /* Change to page 0 and read the intr status reg. */
        outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
        if (ei_debug > 3)
-               printk("%s: interrupt(isr=%#2.2x).\n", dev->name,
+               printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name,
                           inb_p(e8390_base + EN0_ISR));
     
        /* !!Assumption!! -- we stay in page 0.  Don't break this. */
@@ -386,15 +492,16 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
                outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
                if (nr_serviced >= MAX_SERVICE) 
                {
-                       printk("%s: Too much work at interrupt, status %#2.2x\n",
+                       printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",
                                   dev->name, interrupts);
                        outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
                } else {
-                       printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
+                       printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);
                        outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
                }
        }
        dev->interrupt = 0;
+       spin_unlock(&ei_local->page_lock);
        return;
 }
 
@@ -405,6 +512,8 @@ void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
  * letting the failed packet sit and collect dust in the Tx buffer. This
  * is a much better solution as it avoids kernel based Tx timeouts, and
  * an unnecessary card reset.
+ *
+ * Called with lock held
  */
 
 static void ei_tx_err(struct device *dev)
@@ -443,7 +552,7 @@ static void ei_tx_err(struct device *dev)
 }
 
 /* We have finished a transmit: check for errors and then trigger the next
-   packet to be sent. */
+   packet to be sent. Called with lock held */
 
 static void ei_tx_intr(struct device *dev)
 {
@@ -532,7 +641,8 @@ static void ei_tx_intr(struct device *dev)
        mark_bh (NET_BH);
 }
 
-/* We have a good packet(s), get it/them out of the buffers. */
+/* We have a good packet(s), get it/them out of the buffers. 
+   Called with lock held */
 
 static void ei_receive(struct device *dev)
 {
@@ -659,6 +769,8 @@ static void ei_receive(struct device *dev)
  * the updated datasheets, or "the NIC may act in an unpredictable manner."
  * This includes causing "the NIC to defer indefinitely when it is stopped
  * on a busy network."  Ugh.
+ * Called with lock held. Don't call this with the interrupts off or your
+ * computer will hate you - it takes 10mS or so. 
  */
 
 static void ei_rx_overrun(struct device *dev)
@@ -726,19 +838,26 @@ static void ei_rx_overrun(struct device *dev)
                outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
 }
 
+/*
+ *     Collect the stats. This is called unlocked and from several contexts.
+ */
 static struct net_device_stats *get_stats(struct device *dev)
 {
        int ioaddr = dev->base_addr;
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
+       unsigned long flags;
     
        /* If the card is stopped, just return the present stats. */
        if (dev->start == 0) 
                return &ei_local->stat;
 
+       spin_lock_irqsave(&ei_local->page_lock,flags);
        /* Read the counter registers, assuming we are in page 0. */
        ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
        ei_local->stat.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
        ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
     
        return &ei_local->stat;
 }
@@ -794,14 +913,14 @@ static inline void make_mc_bits(u8 *bits, struct device *dev)
 }
 
 /*
- *     Set or clear the multicast filter for this adaptor.
+ *     Set or clear the multicast filter for this adaptor. May be called
+ *     from a BH in 2.1.x. Must be called with lock held. 
  */
  
-static void set_multicast_list(struct device *dev)
+static void do_set_multicast_list(struct device *dev)
 {
        int e8390_base = dev->base_addr;
        int i;
-       unsigned long flags;
        struct ei_device *ei_local = (struct ei_device*)dev->priv;
 
        if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) 
@@ -825,21 +944,19 @@ static void set_multicast_list(struct device *dev)
         * them as r/w so this is a bug.  The SMC 83C790 (SMC Ultra and
         * Ultra32 EISA) appears to have this bug fixed.
         */
+        
        if (dev->start)
                outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
-       save_flags(flags);
-       cli();
        outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
        for(i = 0; i < 8; i++) 
        {
                outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
-#ifdef NOT_83C690
+#ifndef BUG_83C690
                if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i])
                        printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);
 #endif
        }
        outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
-       restore_flags(flags);
 
        if(dev->flags&IFF_PROMISC)
                outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR);
@@ -847,12 +964,29 @@ static void set_multicast_list(struct device *dev)
                outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR);
        else
                outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR);
-}
+ }
+
+/*
+ *     Called without lock held. This is invoked from user context and may
+ *     be parallel to just about everything else. Its also fairly quick and
+ *     not called too often. Must protect against both bh and irq users
+ */
+static void set_multicast_list(struct device *dev)
+{
+       unsigned long flags;
+       struct ei_device *ei_local = (struct ei_device*)dev->priv;
+       
+       spin_lock_irqsave(&ei_local->page_lock, flags);
+       do_set_multicast_list(dev);
+       spin_unlock_irqrestore(&ei_local->page_lock, flags);
+}      
 
 /*
  * Initialize the rest of the 8390 device structure.  Do NOT __initfunc
  * this, as it is used by 8390 based modular drivers too.
  */
+
 int ethdev_init(struct device *dev)
 {
        if (ei_debug > 1)
@@ -867,6 +1001,7 @@ int ethdev_init(struct device *dev)
                        return -ENOMEM;
                memset(dev->priv, 0, sizeof(struct ei_device));
                ei_local = (struct ei_device *)dev->priv;
+               spin_lock_init(&ei_local->page_lock);
        }
     
        dev->hard_start_xmit = &ei_start_xmit;
@@ -883,13 +1018,16 @@ int ethdev_init(struct device *dev)
 /* This page of functions should be 8390 generic */
 /* Follow National Semi's recommendations for initializing the "NIC". */
 
+/*
+ *     Must be called with lock held.
+ */
+
 void NS8390_init(struct device *dev, int startp)
 {
        int e8390_base = dev->base_addr;
        struct ei_device *ei_local = (struct ei_device *) dev->priv;
        int i;
        int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
-       unsigned long flags;
     
        if(sizeof(struct e8390_pkt_hdr)!=4)
                panic("8390.c: header struct mispacked\n");    
@@ -914,8 +1052,7 @@ void NS8390_init(struct device *dev, int startp)
        outb_p(0x00,  e8390_base + EN0_IMR);
     
        /* Copy the station address into the DS8390 registers. */
-       save_flags(flags);
-       cli();
+
        outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
        for(i = 0; i < 6; i++) 
        {
@@ -926,7 +1063,7 @@ void NS8390_init(struct device *dev, int startp)
 
        outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
        outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
-       restore_flags(flags);
+
        dev->tbusy = 0;
        dev->interrupt = 0;
        ei_local->tx1 = ei_local->tx2 = 0;
@@ -940,18 +1077,20 @@ void NS8390_init(struct device *dev, int startp)
                outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
                /* 3c503 TechMan says rxconfig only after the NIC is started. */
                outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on,  */
-               set_multicast_list(dev);        /* (re)load the mcast table */
+               do_set_multicast_list(dev);     /* (re)load the mcast table */
        }
        return;
 }
 
-/* Trigger a transmit start, assuming the length is valid. */
+/* Trigger a transmit start, assuming the length is valid. 
+   Always called with the page lock held */
+   
 static void NS8390_trigger_send(struct device *dev, unsigned int length,
                                                                int start_page)
 {
        int e8390_base = dev->base_addr;
-       struct ei_device *ei_local = (struct ei_device *) dev->priv;
-
+       struct ei_device *ei_local = (struct ei_device *) dev->priv;
+   
        outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD);
     
        if (inb_p(e8390_base) & E8390_TRANS) 
index 52d4e9c9ba90bf6506a89c2712ab19a7675c7d5d..4f280b013f55052eb72354129852be83e4aef403 100644 (file)
@@ -155,30 +155,30 @@ extern void ei_interrupt(int irq, void *dev_id, struct pt_regs *regs);
    things in there should be here!) */
 /* You have one of these per-board */
 struct ei_device {
-  const char *name;
-  void (*reset_8390)(struct device *);
-  void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
-  void (*block_output)(struct device *, int, const unsigned char *, int);
-  void (*block_input)(struct device *, int, struct sk_buff *, int);
-  unsigned char mcfilter[8];
-  unsigned open:1;
-  unsigned word16:1;  /* We have the 16-bit (vs 8-bit) version of the card. */
-  unsigned txing:1;            /* Transmit Active */
-  unsigned irqlock:1;          /* 8390's intrs disabled when '1'. */
-  unsigned dmaing:1;           /* Remote DMA Active */
-  unsigned char tx_start_page, rx_start_page, stop_page;
-  unsigned char current_page;  /* Read pointer in buffer  */
-  unsigned char interface_num; /* Net port (AUI, 10bT.) to use. */
-  unsigned char txqueue;       /* Tx Packet buffer queue length. */
-  short tx1, tx2;              /* Packet lengths for ping-pong tx. */
-  short lasttx;                        /* Alpha version consistency check. */
-  unsigned char reg0;          /* Register '0' in a WD8013 */
-  unsigned char reg5;          /* Register '5' in a WD8013 */
-  unsigned char saved_irq;     /* Original dev->irq value. */
-  /* The new statistics table. */
-  struct net_device_stats stat;
-  unsigned char *reg_offset;    /* Register mapping table */
-  unsigned long priv;          /* Private field to store bus IDs etc. */
+       const char *name;
+       void (*reset_8390)(struct device *);
+       void (*get_8390_hdr)(struct device *, struct e8390_pkt_hdr *, int);
+       void (*block_output)(struct device *, int, const unsigned char *, int);
+       void (*block_input)(struct device *, int, struct sk_buff *, int);
+       unsigned char mcfilter[8];
+       unsigned open:1;
+       unsigned word16:1;              /* We have the 16-bit (vs 8-bit) version of the card. */
+       unsigned txing:1;               /* Transmit Active */
+       unsigned irqlock:1;             /* 8390's intrs disabled when '1'. */
+       unsigned dmaing:1;              /* Remote DMA Active */
+       unsigned char tx_start_page, rx_start_page, stop_page;
+       unsigned char current_page;     /* Read pointer in buffer  */
+       unsigned char interface_num;    /* Net port (AUI, 10bT.) to use. */
+       unsigned char txqueue;          /* Tx Packet buffer queue length. */
+       short tx1, tx2;                 /* Packet lengths for ping-pong tx. */
+       short lasttx;                   /* Alpha version consistency check. */
+       unsigned char reg0;             /* Register '0' in a WD8013 */
+       unsigned char reg5;             /* Register '5' in a WD8013 */
+       unsigned char saved_irq;        /* Original dev->irq value. */
+       struct net_device_stats stat;   /* The new statistics table. */
+       u32 *reg_offset;                /* Register mapping table */
+       spinlock_t page_lock;           /* Page register locks */
+       unsigned long priv;             /* Private field to store bus IDs etc. */
 };
 
 /* The maximum number of 8390 interrupt service routines called per IRQ. */
@@ -190,12 +190,12 @@ struct ei_device {
 #define ei_status (*(struct ei_device *)(dev->priv))
 
 /* Some generic ethernet register configurations. */
-#define E8390_TX_IRQ_MASK 0xa  /* For register EN0_ISR */
-#define E8390_RX_IRQ_MASK  0x5
-#define E8390_RXCONFIG 0x4     /* EN0_RXCR: broadcasts, no multicast,errors */
-#define E8390_RXOFF 0x20       /* EN0_RXCR: Accept no packets */
-#define E8390_TXCONFIG 0x00    /* EN0_TXCR: Normal transmit mode */
-#define E8390_TXOFF 0x02       /* EN0_TXCR: Transmitter off */
+#define E8390_TX_IRQ_MASK      0xa     /* For register EN0_ISR */
+#define E8390_RX_IRQ_MASK      0x5
+#define E8390_RXCONFIG         0x4     /* EN0_RXCR: broadcasts, no multicast,errors */
+#define E8390_RXOFF            0x20    /* EN0_RXCR: Accept no packets */
+#define E8390_TXCONFIG         0x00    /* EN0_TXCR: Normal transmit mode */
+#define E8390_TXOFF            0x02    /* EN0_TXCR: Transmitter off */
 
 /*  Register accessed at EN_CMD, the 8390 base addr.  */
 #define E8390_STOP     0x01    /* Stop and reset the chip */
@@ -208,6 +208,10 @@ struct ei_device {
 #define E8390_PAGE1    0x40    /* using the two high-order bits */
 #define E8390_PAGE2    0x80    /* Page 3 is invalid. */
 
+/*
+ *     Only generate indirect loads given a machine that needs them.
+ */
 #if defined(CONFIG_MAC) || defined(CONFIG_AMIGA_PCMCIA) || \
     defined(CONFIG_ARIADNE2) || defined(CONFIG_ARIADNE2_MODULE)
 #define EI_SHIFT(x)    (ei_local->reg_offset[x])
index 28f1901029b566f54dc7df61748f66b6d911fdaa..5c76aa0d414aa5604b4fb077d522532538ffc74a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cosa.c,v 1.9 1998/12/08 02:24:23 kas Exp $ */
+/* $Id: cosa.c,v 1.11 1998/12/24 23:44:23 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -357,7 +357,7 @@ __initfunc(static int cosa_init(void))
 #endif
 {
        int i;
-       printk(KERN_INFO "cosa v1.02 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
+       printk(KERN_INFO "cosa v1.03 (c) 1997-8 Jan Kasprzak <kas@fi.muni.cz>\n");
 #ifdef __SMP__
        printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
@@ -995,7 +995,9 @@ static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d)
        get_user_ret(len, &(d->len), -EFAULT);
        get_user_ret(code, &(d->code), -EFAULT);
 
-       if (d->len < 0)
+       if (d->addr < 0 || d->addr > COSA_MAX_FIRMWARE_SIZE)
+               return -EINVAL;
+       if (d->len < 0 || d->len > COSA_MAX_FIRMWARE_SIZE)
                return -EINVAL;
 
        if ((i=download(cosa, d->code, len, addr)) < 0) {
@@ -1555,6 +1557,15 @@ static int puthexnumber(struct cosa_data *cosa, int number)
  * separate functions to make it more readable. These functions are inline,
  * so there should be no overhead of function call.
  */
+
+/*
+ * Transmit interrupt routine - called when COSA is willing to obtain
+ * data from the OS. The most tricky part of the routine is selection
+ * of channel we (OS) want to send packet for. For SRP we should probably
+ * use the round-robin approach. The newer COSA firmwares have a simple
+ * flow-control - in the status word has bits 2 and 3 set to 1 means that the
+ * channel 0 or 1 doesn't want to receive data.
+ */
 static inline void tx_interrupt(struct cosa_data *cosa, int status)
 {
        unsigned long flags, flags1;
@@ -1564,16 +1575,24 @@ static inline void tx_interrupt(struct cosa_data *cosa, int status)
 #endif
        spin_lock_irqsave(&cosa->lock, flags);
        set_bit(TXBIT, &cosa->rxtx);
-       /*
-        * Using a round-robin algorithm select a first channel that has
-        * data ready for transmit.
-        */
        if (!test_bit(IRQBIT, &cosa->rxtx)) {
+               /* flow control */
+               int i=0;
                do {
+                       if (i++ > cosa->nchannels) {
+                               printk(KERN_WARNING
+                                       "%s: No channel wants data in TX IRQ\n",
+                                       cosa->name);
+                               clear_bit(TXBIT, &cosa->rxtx);
+                               spin_unlock_irqrestore(&cosa->lock, flags);
+                               return;
+                       }
                        cosa->txchan++;
                        if (cosa->txchan >= cosa->nchannels)
                                cosa->txchan = 0;
-               } while(!(cosa->txbitmap & (1<<cosa->txchan)));
+               } while ((!(cosa->txbitmap & (1<<cosa->txchan)))
+                       || status & (1<<(cosa->txchan+DRIVER_TXMAP_SHIFT)));
+
                cosa->txsize = cosa->chan[cosa->txchan].txsize;
                if (cosa_dma_able(cosa->chan+cosa->txchan,
                        cosa->chan[cosa->txchan].txbuf, cosa->txsize)) {
index 10ea328048db8883ad51baf7dca93ba9d1b244e8..09f2e243d2848c5b72794bd0e01d3be1463dbf77 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: cosa.h,v 1.8 1998/11/09 03:54:49 kas Exp $ */
+/* $Id: cosa.h,v 1.5 1998/12/24 12:40:18 kas Exp $ */
 
 /*
  *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
@@ -61,7 +61,7 @@
 #define SR_START_ADDR   0x4400  /* SRP microcode start address */
 
 #define COSA_LOAD_ADDR    0x400  /* SRP microcode load address */
-
+#define COSA_MAX_FIRMWARE_SIZE 0x10000
 
 /* ioctls */
 struct cosa_download {
index f0f6c1ac80585115f5cb89ea3ecea504a3f473a7..65998365579e72e5770f2c238ab9cade7e51b90e 100644 (file)
@@ -303,6 +303,10 @@ static int io[MAX_CARDS] = { 0, };
 static int dma[MAX_CARDS] = { 0, };
 static int irq[MAX_CARDS]  = { 0, };
 
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+
 static char ifnames[MAX_CARDS][IF_NAMELEN] = { {0, }, };
 static struct device dev_lance[MAX_CARDS] =
 {{
@@ -363,11 +367,12 @@ int lance_probe(struct device *dev)
 {
        int *port, result;
 
-       if (high_memory <= 16*1024*1024)
+       if (high_memory <= phys_to_virt(16*1024*1024))
                lance_need_isa_bounce_buffers = 0;
 
 #if defined(CONFIG_PCI)
-    if (pci_present()) {
+       if (pci_present()) 
+       {
                struct pci_dev *pdev = NULL;
                if (lance_debug > 1)
                        printk("lance.c: PCI bios is present, checking for devices...\n");
index 00454c5d63aaa920d721ae6981b4c5af2fe9ac0b..3c7eef8c216a0888dca26f0eb43c5c7f29641f4f 100644 (file)
 * Jan 02, 1997 Gene Kozin      Initial version.
 *****************************************************************************/
 
-#if    !defined(__KERNEL__) || !defined(MODULE)
-#error This code MUST be compiled as a kernel module!
-#endif
-
 #include <linux/config.h>      /* OS configuration options */
 #include <linux/stddef.h>      /* offsetof(), etc. */
 #include <linux/errno.h>       /* return codes */
@@ -122,7 +118,12 @@ static struct tq_struct sdla_tq =
  *             < 0     error.
  * Context:    process
  */
+#ifdef MODULE
 int init_module (void)
+#else
+int wanpipe_init(void)
+#endif
 {
        int cnt, err = 0;
 
@@ -173,6 +174,7 @@ int init_module (void)
        return err;
 }
 
+#ifdef MODULE
 /*============================================================================
  * Module 'remove' entry point.
  * o unregister all adapters from the WAN router
@@ -190,6 +192,8 @@ void cleanup_module (void)
        kfree(card_array);
 }
 
+#endif
+
 /******* WAN Device Driver Entry Points *************************************/
 
 /*============================================================================
index 53e3b211509858a1a247ba1b3c587f1fb8062988..19a937c41fd2dc12dc12e5823dc430ec667ac78c 100644 (file)
@@ -66,6 +66,7 @@ static const int multicast_filter_limit = 32;
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/version.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
index a3e37481513d3383a957ca6cc68af5201e3fc5a3..920e90a4b6f8d77992bebba07cc83cc06bb99541 100644 (file)
@@ -389,9 +389,11 @@ static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int l
      * In case you are wondering what the last line of the asm does...
      * <output allocation> : <input allocation> : <trashed registers>
      */
+    register int d0;
+
     asm("shr $2,%%ecx\n" \
        "       jz .no_more_bulk_bo\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_bulk_bo:\n" \
        "       movl (%%esi),%%ebx\n" \
        BYTE_OUT(%%bl) \
@@ -401,19 +403,23 @@ static inline int ppa_byte_out(unsigned short base, char *buffer, unsigned int l
        BYTE_OUT(%%bh) \
        "       addl $4,%%esi\n" \
        "       loop .loop_bulk_bo\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".no_more_bulk_bo:" \
-  : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
+  : "=S"(buffer), "=c"(d0)
+  : "1"(len), "d"(base), "0"(buffer)
+  : "eax", "ebx");
 
     asm("andl $3,%%ecx\n" \
        "       jz .no_more_loose_bo\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_loose_bo:\n" \
        BYTE_OUT((%%esi)) \
        "       incl %%esi\n" \
        "       loop .loop_loose_bo\n" \
        ".no_more_loose_bo:\n" \
-  : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
+  : "=c"(d0)
+  : "0"(len), "d"(base), "S"(buffer)
+  : "eax", "ebx");
     return 1;                  /* All went well - we hope! */
 }
 
@@ -439,9 +445,11 @@ static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
      * In case you are wondering what the last line of the asm does...
      * <output allocation> : <input allocation> : <trashed registers>
      */
+    register int d0;
+
     asm("shr $2,%%ecx\n" \
        "       jz .no_more_bulk_bi\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_bulk_bi:\n" \
        BYTE_IN(%%bl) \
        BYTE_IN(%%bh) \
@@ -452,19 +460,23 @@ static inline int ppa_byte_in(unsigned short base, char *buffer, int len)
        "       movl %%ebx,(%%esi)\n" \
        "       addl $4,%%esi\n" \
        "       loop .loop_bulk_bi\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".no_more_bulk_bi:" \
-  : "=S"(buffer): "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
+  : "=S"(buffer), "=c"(d0)
+  : "1"(len), "d"(base), "0"(buffer)
+  : "eax", "ebx");
 
     asm("andl $3,%%ecx\n" \
        "       jz .no_more_loose_bi\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_loose_bi:\n" \
        BYTE_IN((%%esi)) \
        "       incl %%esi\n" \
        "       loop .loop_loose_bi\n" \
        ".no_more_loose_bi:\n" \
-  : /* no output */ : "c"(len), "d"(base), "S"(buffer):"eax", "ebx", "ecx");
+  : "=c"(d0)
+  : "0"(len), "d"(base), "S"(buffer)
+  : "eax", "ebx");
     return 1;                  /* All went well - we hope! */
 }
 
@@ -496,9 +508,11 @@ static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
      * In case you are wondering what the last line of the asm does...
      * <output allocation> : <input allocation> : <trashed registers>
      */
+    register int d0;
+
     asm("shr $2,%%ecx\n" \
        "       jz .no_more_bulk_ni\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_bulk_ni:\n" \
        NIBBLE_IN(%%bl) \
        NIBBLE_IN(%%bh) \
@@ -509,19 +523,23 @@ static inline int ppa_nibble_in(unsigned short str_p, char *buffer, int len)
        "       movl %%ebx,(%%esi)\n" \
        "       addl $4,%%esi\n" \
        "       loop .loop_bulk_ni\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".no_more_bulk_ni:" \
-  : "=S"(buffer): "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
+  : "=S"(buffer), "=c"(d0)
+  : "1"(len), "d"(str_p), "0"(buffer)
+  : "eax", "ebx");
 
     asm("andl $3,%%ecx\n" \
        "       jz .no_more_loose_ni\n" \
-       "       .align 4\n" \
+       "       .p2align 4,,7\n" \
        ".loop_loose_ni:\n" \
        NIBBLE_IN((%%esi)) \
        "       incl %%esi\n" \
        "       loop .loop_loose_ni\n" \
        ".no_more_loose_ni:\n" \
-  : /* no output */ : "c"(len), "d"(str_p), "S"(buffer):"eax", "ebx", "ecx");
+  : "=c"(d0)
+  : "0"(len), "d"(str_p), "S"(buffer)
+  : "eax", "ebx");
     return 1;                  /* All went well - we hope! */
 }
 #else                          /* Old style C routines */
index e759ae81903375d2d765ae82d78a458a62ad1ef1..d95a647272c8a1db88954bfdabe0001a0f33fedb 100644 (file)
@@ -2678,7 +2678,7 @@ static int joystick[NR_DEVICE] = { 0, };
 
 /* --------------------------------------------------------------------- */
 
-static const struct initvol {
+static struct initvol {
        int mixch;
        int vol;
 } initvol[] __initdata = {
index 489c2c7c08c09ca6ce1c47c2eb65a5345394f3f3..f1843f76ab6ae823e70b05d5e1fe2c55eded311e 100644 (file)
@@ -65,6 +65,8 @@
  *                             Improved debugging support.     16-May-1998
  *                             Fixed bug.                      16-Jun-1998
  *
+ *     Torsten Duwe            Made Opti924 PnP support non-destructive
+ *                                                             1998-12-23
  */
 
 #include "sound_config.h"
@@ -279,19 +281,21 @@ static int detect_c930(void)
        if ((mad_read(MC0_PORT+13) & 0x80) == 0)
                return 1;
        
+#if 0  
        /* Force off PnP mode. This is not recommended because
         * the PnP bios will not recognize the chip on the next
         * warm boot and may assignd different resources to other
         * PnP/PCI cards.
         */
        mad_write(MC0_PORT+17, 0x04);
+#endif
        return 1;
 }
 
 static int detect_mad16(void)
 {
-       unsigned char tmp, tmp2;
-       int i;
+       unsigned char tmp, tmp2, bit;
+       int i, port;
 
        /*
         * Check that reading a register doesn't return bus float (0xff)
@@ -323,14 +327,19 @@ static int detect_mad16(void)
                DDB(printk("MC1_PORT didn't close after read (0x%02x)\n", tmp2));
                return 0;
        }
-       mad_write(MC1_PORT, tmp ^ 0x80);        /* Toggle a bit */
-       if ((tmp2 = mad_read(MC1_PORT)) != (tmp ^ 0x80))        /* Compare the bit */
+
+       bit  = (c924pnp) ?     0x20 : 0x80;
+       port = (c924pnp) ? MC2_PORT : MC1_PORT;
+
+       tmp = mad_read(port);
+       mad_write(port, tmp ^ bit);     /* Toggle a bit */
+       if ((tmp2 = mad_read(port)) != (tmp ^ bit))     /* Compare the bit */
        {
-               mad_write(MC1_PORT, tmp);       /* Restore */
+               mad_write(port, tmp);   /* Restore */
                DDB(printk("Bit revert test failed (0x%02x, 0x%02x)\n", tmp, tmp2));
                return 0;
        }
-       mad_write(MC1_PORT, tmp);       /* Restore */
+       mad_write(port, tmp);   /* Restore */
        return 1;               /* Bingo */
 }
 
@@ -456,14 +465,8 @@ static int chip_detect(void)
 
        DDB(printk("Detect using password = 0xE5\n"));
        
-       if (!detect_mad16()) {
-               c924pnp++;
-               DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
-       }
-
        if (!detect_mad16())    /* No luck. Try different model */
        {
-               c924pnp=0;
                board_type = C928;
 
                DDB(printk("Detect using password = 0xE2\n"));
@@ -493,10 +496,19 @@ static int chip_detect(void)
                                for (i = 0xf8d; i <= 0xf93; i++)
                                        DDB(printk("port %03x = %02x\n", i, mad_read(i)));
 
-                               if (!detect_mad16())
-                                       return 0;
-
-                               DDB(printk("mad16.c: 82C930 detected\n"));
+                               if (!detect_mad16()) {
+                                 board_type = C924;
+                                 c924pnp++;
+                                 DDB(printk("Detect using password = 0xE5 (again), port offset -0x80\n"));
+                                 if (!detect_mad16()) {
+                                   c924pnp=0;
+                                   return 0;
+                                 }
+                                 
+                                 DDB(printk("mad16.c: 82C924 PnP detected\n"));
+                               }
+                               else
+                                 DDB(printk("mad16.c: 82C930 detected\n"));
                        } else
                                DDB(printk("mad16.c: 82C929 detected\n"));
                } else {
index 3414387488423fd4445d1715dd6df9ebc751192d..8be3b91a92d54bdeec537aed8897de45c85b49f5 100644 (file)
@@ -260,7 +260,6 @@ void unload_opl3sa_wss(struct address_info *hw_config)
                      hw_config->dma,
                      dma2,
                      0);
-       sound_unload_audiodev(hw_config->slots[0]);
 }
 
 void unload_opl3sa_mpu(struct address_info *hw_config)
index 16fcba273d3a21c025aec604b4649ea6e31099bb..9f09bd28bbd2bd261544a8db0819676240c23943 100644 (file)
@@ -48,7 +48,7 @@
 #define MDL_ES1868MIDI 14      /* MIDI port of ESS1868 */
 #define MDL_AEDSP      15      /* Audio Excel DSP 16 */
 
-#define SUBMDL_ES18XX  0x10    /* Introduced a subtype ESS 18XX (Rolf) */
+#define SUBMDL_ES188X  0x10    /* Subtype ES188X for specific handling */
 #define SUBMDL_ALS007  42      /* ALS-007 differs from SB16 only in mixer */
                                /* register assignment */
 /*
index b05d7eb2d915d01e8115660e1277fe72ebc2e938..0311f3f1a529347b7aa13a12bb09c6a7083d339b 100644 (file)
@@ -13,8 +13,8 @@
 /*
  * Daniel J. Rodriksson: Modified sbintr to handle 8 and 16 bit interrupts
  *                       for full duplex support ( only sb16 by now )
- * Rolf Fokkens:        Added (BETA?) support for ES18XX chips.
- *                      Which means: you can adjust the recording levels.
+ * Rolf Fokkens:        Added (BETA?) support for ES188x chips.
+ * (fokkensr@vertis.nl)         Which means: You can adjust the recording levels.
  */
 #include <linux/config.h>
 #include <linux/delay.h>
@@ -545,8 +545,9 @@ static int ess_init(sb_devc * devc, struct address_info *hw_config)
 
        /*
         * This the detection heuristic of ESS technology, though somewhat
-        * changed to actually make it work :-)
-        * This is the most BETA part of the software: Will it work?
+        * changed to actually make it work.
+        * This is the most BETA part of the software: Will the detection
+         * always work?
         */
        devc->model = MDL_ESS;
        devc->submodel = ess_minor & 0x0f;
@@ -558,8 +559,8 @@ static int ess_init(sb_devc * devc, struct address_info *hw_config)
                if ((ess_minor & 0x0f) >= 8) {
                        if (  !ess_probe (devc, 0x64, (1 << 3))
                            && ess_probe (devc, 0x70, 0x7f)) {
-                               chip = "ES18XX";
-                               devc->submodel = SUBMDL_ES18XX;
+                               chip = "ES188x";
+                               devc->submodel = SUBMDL_ES188X;
                        } else {
                                chip = "ES1688";
                        };
@@ -1035,7 +1036,7 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
 /*
  *     Mixer access routines
  *
- *     ES18XX modifications: some mixer registers reside in the
+ *     ES188x modifications: some mixer registers reside in the
  *     range above 0xa0. These must be accessed in another way.
  */
 
index a96c4e3921180320abb3722b8b7ef2a9779f53ab..465f9cbdca7bfc5a73be9b3760168d98b9e516cf 100644 (file)
  *
  *
  * Thomas Sailer   : ioctl code reworked (vmalloc/vfree removed)
- * Rolf Fokkens    : ES18XX recording level support
+ * Rolf Fokkens    : ES188x recording level support
  */
 
 /*
- * About ES18XX support:
+ * About ES188x support:
  *
- * The standard ES688 support doesn't take care of the ES18XX recording
+ * The standard ES1688 support doesn't take care of the ES188x recording
  * levels very well. Whenever a device is selected (recmask) for recording
  * it's recording level is loud, and it cannot be changed.
  *
- * The ES18XX has separate registers to controll the recording levels. The
- * ES18XX specific software makes these level the same as their corresponding
- * playback levels, unless recmask says they aren't recorded. In tha latter
- * case the recording volumens are 0.
+ * The ES188x has separate registers to control the recording levels. The
+ * ES188x specific software makes these level the same as their corresponding
+ * playback levels, unless recmask says they aren't recorded. In the latter
+ * case the recording volumes are 0.
  *
  * Now recording levels of inputs can be controlled, by changing the playback
- * levels.
- * Futhermore several devices can be recorded together (which is not possible
- * with the ES688.
+ * levels. Futhermore several devices can be recorded together (which is not
+ * possible with the ES1688.
  */
 
 #include <linux/config.h>
@@ -139,13 +138,13 @@ static int common_mixer_set(sb_devc * devc, int dev, int left, int right)
 }
 
 /*
- * Changing input levels at ES18XX means having to take care of recording
- * levels of recorded inputs too!
+ * Changing playback levels at ES188x means having to take care of recording
+ * levels of recorded inputs (devc->recmask) too!
  */
-static int es18XX_mixer_set(sb_devc * devc, int dev, int left, int right)
+static int es188x_mixer_set(sb_devc * devc, int dev, int left, int right)
 {
        if (devc->recmask & (1 << dev)) {
-               common_mixer_set(devc, dev + ES18XX_MIXER_RECDIFF, left, right);
+               common_mixer_set(devc, dev + ES188X_MIXER_RECDIFF, left, right);
        }
        return common_mixer_set(devc, dev, left, right);
 }
@@ -212,8 +211,8 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value)
                return smw_mixer_set(devc, dev, left, right);
                break;
        case MDL_ESS:
-               if (devc->submodel == SUBMDL_ES18XX) {
-                       return es18XX_mixer_set(devc, dev, left, right);
+               if (devc->submodel == SUBMDL_ES188X) {
+                       return es188x_mixer_set(devc, dev, left, right);
                }
                break;
        }
@@ -222,7 +221,7 @@ static int sb_mixer_set(sb_devc * devc, int dev, int value)
 }
 
 /*
- * set_recsrc doesn't apply to ES18XX
+ * set_recsrc doesn't apply to ES188x
  */
 static void set_recsrc(sb_devc * devc, int src)
 {
@@ -230,12 +229,12 @@ static void set_recsrc(sb_devc * devc, int src)
 }
 
 /*
- * Changing the recmask on a ES18XX means:
+ * Changing the recmask on a ES188x means:
  * (1) Find the differences
  * (2) For "turned-on"  inputs: make the recording level the playback level
  * (3) For "turned-off" inputs: make the recording level zero
  */
-static int es18XX_set_recmask(sb_devc * devc, int mask)
+static int es188x_set_recmask(sb_devc * devc, int mask)
 {
        int i, i_mask, cur_mask, diff_mask;
        int value, left, right;
@@ -245,16 +244,16 @@ static int es18XX_set_recmask(sb_devc * devc, int mask)
 
        for (i = 0; i < 32; i++) {
                i_mask = (1 << i);
-               if (diff_mask & i_mask) {
-                       if (mask & i_mask) {    /* Turn it on (2) */
+               if (diff_mask & i_mask) {       /* Difference? (1)      */
+                       if (mask & i_mask) {    /* Turn it on  (2)      */
                                value = devc->levels[i];
                                left  = value & 0x000000ff;
                                right = (value & 0x0000ff00) >> 8;
-                       } else {                /* Turn it off (3) */
+                       } else {                /* Turn it off (3)      */
                                left  = 0;
                                right = 0;
                        }
-                       common_mixer_set(devc, i + ES18XX_MIXER_RECDIFF, left, right);
+                       common_mixer_set(devc, i + ES188X_MIXER_RECDIFF, left, right);
                }
        }
        return mask;
@@ -269,14 +268,18 @@ static int set_recmask(sb_devc * devc, int mask)
 
        switch (devc->model)
        {
-               case MDL_ESS:   /* ES18XX needs a separate approach */
-                       if (devc->submodel == SUBMDL_ES18XX) {
-                               devmask = es18XX_set_recmask(devc, devmask);
-                               break;
-                       };
                case MDL_SBPRO:
+               case MDL_ESS:
                case MDL_JAZZ:
                case MDL_SMW:
+                       if (devc->model == MDL_ESS &&
+                               devc->submodel == SUBMDL_ES188X) {
+                               /*
+                                * ES188x needs a separate approach
+                                */
+                               devmask = es188x_set_recmask(devc, devmask);
+                               break;
+                       };
 
                        if (devmask != SOUND_MASK_MIC &&
                                devmask != SOUND_MASK_LINE &&
@@ -507,12 +510,12 @@ static void sb_mixer_reset(sb_devc * devc)
                sb_mixer_set(devc, i, devc->levels[i]);
 
        /*
-        * Separate actions for ES18XX:
-        * Change registers 7a and 1c to make the record mixer the input for
-        *
-        * Then call set_recmask twice to do extra ES18XX initializations
+        * Separate actions for ES188x:
+        * Change registers 7a and 1c to make the record mixer the
+        * actual recording source.
+        * Then call set_recmask twice to do extra ES188x initializations
         */
-       if (devc->model == MDL_ESS && devc->submodel == SUBMDL_ES18XX) {
+       if (devc->model == MDL_ESS && devc->submodel == SUBMDL_ES188X) {
                regval = sb_getmixer(devc, 0x7a);
                regval = (regval & 0xe7) | 0x08;
                sb_setmixer(devc, 0x7a, regval);
@@ -520,7 +523,7 @@ static void sb_mixer_reset(sb_devc * devc)
                regval = (regval & 0xf8) | 0x07;
                sb_setmixer(devc, 0x1c, regval);
 
-               set_recmask(devc, ES18XX_RECORDING_DEVICES);
+               set_recmask(devc, ES188X_RECORDING_DEVICES);
                set_recmask(devc, 0);
        }
        set_recmask(devc, SOUND_MASK_MIC);
@@ -554,15 +557,15 @@ int sb_mixer_init(sb_devc * devc)
                        devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
 
                        /*
-                        * Take care of ES18XX specifics...
+                        * Take care of ES188x specifics...
                         */
                        switch (devc->submodel) {
-                       case SUBMDL_ES18XX:
+                       case SUBMDL_ES188X:
                                devc->supported_devices
-                                       = ES18XX_MIXER_DEVICES;
+                                       = ES188X_MIXER_DEVICES;
                                devc->supported_rec_devices
-                                       = ES18XX_RECORDING_DEVICES;
-                               devc->iomap = &es18XX_mix;
+                                       = ES188X_RECORDING_DEVICES;
+                               devc->iomap = &es188x_mix;
                                break;
                        default:
                                devc->supported_devices
index 2785567e5bebe6ccfec896ce22af8643e1d31bf2..00dd031a6eea7f55baa55188601c8c156771d444 100644 (file)
@@ -17,7 +17,7 @@
  *     Added defines for the Sound Galaxy NX Pro mixer.
  *
  *     Rolf Fokkens    Dec 20 1998
- *     Added (BETA?) support for ES18XX chips.
+ *     Added (BETA?) support for ES188x chips.
  *     Which means: you can adjust the recording levels.
  *
  */
@@ -51,9 +51,9 @@
 #define ES688_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
 #define ES688_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_LINE2|SOUND_MASK_SPEAKER)
 
-#define ES18XX_RECORDING_DEVICES       (ES688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
+#define ES188X_RECORDING_DEVICES       (ES688_RECORDING_DEVICES | SOUND_MASK_LINE2 \
                                         |SOUND_MASK_SYNTH)
-#define ES18XX_MIXER_DEVICES (ES688_MIXER_DEVICES)
+#define ES188X_MIXER_DEVICES (ES688_MIXER_DEVICES)
 
 #define SB16_MIXER_DEVICES             (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
                                         SOUND_MASK_CD | \
 #define RIGHT_CHN      1
 
 /*
- * Mixer registers of ES18XX
+ * Mixer registers of ES188x
  *
  * These register specifically take care of recording levels. To make the
  * mapping from playback devices to recording devices every recording
- * devices = playback device + ES18XX_MIXER_RECDIFF
+ * devices = playback device + ES188X_MIXER_RECDIFF
  */
-#define ES18XX_MIXER_RECBASE   (SOUND_MIXER_LINE3 + 1)
-#define ES18XX_MIXER_RECDIFF   (ES18XX_MIXER_RECBASE - SOUND_MIXER_SYNTH)
-
-#define ES18XX_MIXER_RECSYNTH  (SOUND_MIXER_SYNTH      + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECPCM    (SOUND_MIXER_PCM        + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECSPEAKER        (SOUND_MIXER_SPEAKER    + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECLINE   (SOUND_MIXER_LINE       + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECMIC    (SOUND_MIXER_MIC        + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECCD     (SOUND_MIXER_CD         + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECIMIX   (SOUND_MIXER_IMIX       + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM     + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECRECLEV (SOUND_MIXER_RECLEV     + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECIGAIN  (SOUND_MIXER_IGAIN      + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECOGAIN  (SOUND_MIXER_OGAIN      + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECLINE1  (SOUND_MIXER_LINE1      + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECLINE2  (SOUND_MIXER_LINE2      + ES18XX_MIXER_RECDIFF)
-#define ES18XX_MIXER_RECLINE3  (SOUND_MIXER_LINE3      + ES18XX_MIXER_RECDIFF)
+#define ES188X_MIXER_RECBASE   (SOUND_MIXER_LINE3 + 1)
+#define ES188X_MIXER_RECDIFF   (ES188X_MIXER_RECBASE - SOUND_MIXER_SYNTH)
+
+#define ES188X_MIXER_RECSYNTH  (SOUND_MIXER_SYNTH      + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECPCM    (SOUND_MIXER_PCM        + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECSPEAKER        (SOUND_MIXER_SPEAKER    + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE   (SOUND_MIXER_LINE       + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECMIC    (SOUND_MIXER_MIC        + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECCD     (SOUND_MIXER_CD         + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIMIX   (SOUND_MIXER_IMIX       + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECALTPCM (SOUND_MIXER_ALTPCM     + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECRECLEV (SOUND_MIXER_RECLEV     + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECIGAIN  (SOUND_MIXER_IGAIN      + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECOGAIN  (SOUND_MIXER_OGAIN      + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE1  (SOUND_MIXER_LINE1      + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE2  (SOUND_MIXER_LINE2      + ES188X_MIXER_RECDIFF)
+#define ES188X_MIXER_RECLINE3  (SOUND_MIXER_LINE3      + ES188X_MIXER_RECDIFF)
 
 /*
  * Mixer registers of ALS007
@@ -188,13 +188,15 @@ MIX_ENT(SOUND_MIXER_LINE3,        0x00, 0, 0, 0x00, 0, 0)
 };
 
 /*
- * The ES18XX specifics.
- * Note that de master volume unlike ES688 is now controlled by two 
- * 6 bit registers.
- * Also Note that the recording levels (ES18XX_MIXER_REC...) have own 
- * entries as if they were playback devices. They are used internally only!
+ * The ES188x specifics.
+ * Note that de master volume unlike ES688 is now controlled by two 6 bit
+ * registers. These seem to work OK on 1868 too, but I have no idea if it's
+ * compatible to 688 or 1688....
+ * Also Note that the recording levels (ES188X_MIXER_REC...) have own 
+ * entries as if they were playback devices. They are used internally in the
+ * driver only!
  */
-static mixer_tab es18XX_mix = {
+static mixer_tab es188x_mix = {
 MIX_ENT(SOUND_MIXER_VOLUME,    0x60, 5, 6, 0x62, 5, 6),
 MIX_ENT(SOUND_MIXER_BASS,       0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,     0x00, 0, 0, 0x00, 0, 0),
@@ -212,21 +214,21 @@ MIX_ENT(SOUND_MIXER_OGAIN,      0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_LINE1,      0x00, 0, 0, 0x00, 0, 0),
 MIX_ENT(SOUND_MIXER_LINE2,      0x3a, 7, 4, 0x3a, 3, 4),
 MIX_ENT(SOUND_MIXER_LINE3,      0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
-MIX_ENT(ES18XX_MIXER_RECPCM,   0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECSPEAKER,0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECLINE,  0x6e, 7, 4, 0x6e, 3, 4),
-MIX_ENT(ES18XX_MIXER_RECMIC,   0x68, 7, 4, 0x68, 3, 4),
-MIX_ENT(ES18XX_MIXER_RECCD,    0x6a, 7, 4, 0x6a, 3, 4),
-
-MIX_ENT(ES18XX_MIXER_RECIMIX,  0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECALTPCM,        0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECRECLEV,        0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
-MIX_ENT(ES18XX_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
-MIX_ENT(ES18XX_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
+MIX_ENT(ES188X_MIXER_RECSYNTH, 0x6b, 7, 4, 0x6b, 3, 4),
+MIX_ENT(ES188X_MIXER_RECPCM,   0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECSPEAKER,0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE,  0x6e, 7, 4, 0x6e, 3, 4),
+MIX_ENT(ES188X_MIXER_RECMIC,   0x68, 7, 4, 0x68, 3, 4),
+MIX_ENT(ES188X_MIXER_RECCD,    0x6a, 7, 4, 0x6a, 3, 4),
+
+MIX_ENT(ES188X_MIXER_RECIMIX,  0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECALTPCM,        0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECRECLEV,        0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECIGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECOGAIN, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE1, 0x00, 0, 0, 0x00, 0, 0),
+MIX_ENT(ES188X_MIXER_RECLINE2, 0x6c, 7, 4, 0x6c, 3, 4),
+MIX_ENT(ES188X_MIXER_RECLINE3, 0x00, 0, 0, 0x00, 0, 0)
 };
 
 #ifdef __SGNXPRO__
index 0a36930d9e7e70bb0e140040a4d6519f123bfb39..2c6394fe26592ce6e35c2d25b5ac31b81d42c1a6 100644 (file)
@@ -103,6 +103,10 @@ int autofs_wait(struct autofs_sb_info *sbi, struct qstr * name)
        struct autofs_wait_queue *wq;
        int status;
 
+       /* In catatonic mode, we don't wait for nobody */
+       if ( sbi->catatonic )
+               return -ENOENT;
+
        for ( wq = sbi->queues ; wq ; wq = wq->next ) {
                if ( wq->hash == name->hash &&
                     wq->len == name->len &&
@@ -138,6 +142,15 @@ int autofs_wait(struct autofs_sb_info *sbi, struct qstr * name)
 
        /* wq->name is NULL if and only if the lock is already released */
 
+       if ( sbi->catatonic ) {
+               /* We might have slept, so check again for catatonic mode */
+               wq->status = -ENOENT;
+               if ( wq->name ) {
+                       kfree(wq->name);
+                       wq->name = NULL;
+               }
+       }
+
        if ( wq->name ) {
                /* Block all but "shutdown" signals while waiting */
                sigset_t oldset;
index 2eb7b13af6b386a63693bbedcdabc817d146f8d3..0bf373cf82dc0022b75c8459f42e5defa30a6594 100644 (file)
@@ -592,9 +592,10 @@ struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
        struct list_head *head = d_hash(parent,hash);
        struct list_head *tmp = head->next;
 
-       while (tmp != head) {
+       for (;;) {
                struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);
-
+               if (tmp == head)
+                       break;
                tmp = tmp->next;
                if (dentry->d_name.hash != hash)
                        continue;
index e123a9f1648d0a88eceeeb7455d7cef71dc87f64..9c45967c049317cea86f29b85707f811864e9da4 100644 (file)
@@ -428,7 +428,7 @@ fat_read_super(struct super_block *sb, void *data, int silent)
                       MSDOS_SB(sb)->fat_bits,opts.name_check,
                       opts.conversion,opts.fs_uid,opts.fs_gid,opts.fs_umask,
                       MSDOS_CAN_BMAP(MSDOS_SB(sb)) ? ",bmap" : "");
-               printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
+               printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%ld,ds=%ld,de=%d,data=%ld,"
                       "se=%d,ts=%ld,ls=%d,rc=%ld,fc=%u]\n",
                        b->media,MSDOS_SB(sb)->cluster_size,
                        MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,
index 329605a12057016f825400fd77cd8328346c1b47..9ed3a88671b95b66e50acbc0ba9ad490c63058a3 100644 (file)
@@ -438,6 +438,7 @@ parent->d_name.name, dentry->d_name.name);
 
        /* Ok, remeber that we successfully checked it.. */
        nfs_renew_times(dentry);
+       nfs_refresh_inode(inode, &fattr);
 
 out_valid:
        return 1;
index b8bbb3919eb443f88809a8d32ab78e62ff36837f..9689f815820d3439fdd86253d25b456d1a25ba38 100644 (file)
@@ -701,12 +701,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name, inode->i_ino, status);
 #endif
                goto out;
        }
-       if (fattr.mtime.seconds == NFS_OLDMTIME(inode)) {
-               /* Update attrtimeo value */
-               if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))
-                       NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);
-       }
-       NFS_OLDMTIME(inode) = fattr.mtime.seconds;
        dfprintk(PAGECACHE, "NFS: %s/%s revalidation complete\n",
                dentry->d_parent->d_name.name, dentry->d_name.name);
 out:
@@ -791,6 +785,14 @@ printk("NFS: mtime change on %x/%ld\n", inode->i_dev, inode->i_ino);
 
        if (invalid)
                goto out_invalid;
+
+       /* Update attrtimeo value */
+       if (fattr->mtime.seconds == NFS_OLDMTIME(inode)) {
+               if ((NFS_ATTRTIMEO(inode) <<= 1) > NFS_MAXATTRTIMEO(inode))
+                       NFS_ATTRTIMEO(inode) = NFS_MAXATTRTIMEO(inode);
+       }
+       NFS_OLDMTIME(inode) = fattr->mtime.seconds;
+
 out:
        return error;
 
index 3399a9684d1dcc94d172a83e78cb4db50a2a0f63..6dd4b33f05574db191779525de56dcc9877a712a 100644 (file)
@@ -167,11 +167,11 @@ static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
  * to devices.
  *
  * For now, "wmb()" doesn't actually do anything, as all
- * intel CPU's follow what intel calls a *Processor Order*,
+ * Intel CPU's follow what Intel calls a *Processor Order*,
  * in which all writes are seen in the program order even
  * outside the CPU.
  *
- * I expect future intel CPU's to have a weaker ordering,
+ * I expect future Intel CPU's to have a weaker ordering,
  * but I'd also expect them to finally get their act together
  * and add some real memory barriers if so.
  */
index 4cd811e9a2cf7040762741c0e7d2db4adebbffba..10b18b433d372cdd45946f6bce26e5300dd8f483 100644 (file)
 /*
  * Standard way to access the cycle counter on i586+ CPUs.
  * Currently only used on SMP.
+ *
+ * If you really have a SMP machine with i486 chips or older,
+ * compile for that, and this will just always return zero.
+ * That's ok, it just means that the nicer scheduling heuristics
+ * won't work for you.
+ *
+ * We only use the low 32 bits, and we'd simply better make sure
+ * that we reschedule before that wraps. Scheduling at least every
+ * four billion cycles just basically sounds like a good idea,
+ * regardless of how fast the machine is. 
  */
-typedef unsigned long long cycles_t;
+typedef unsigned long cycles_t;
 
 extern cycles_t cacheflush_time;
 
 static inline cycles_t get_cycles (void)
 {
-       cycles_t value;
+#if CPU < 586
+       return 0;
+#else
+       unsigned long eax, edx;
 
-       __asm__("rdtsc"
-               :"=a" (*(((int *)&value)+0)),
-                "=d" (*(((int *)&value)+1)));
-       return value;
+       __asm__("rdtsc":"=a" (eax), "=d" (edx));
+       return eax;
+#endif
 }
 
 #endif
index 96469a0bdb63ffe3e1b34ba33d1fd28c3bcdb87f..20589194f0e40a6cc75f1a5c8fef765f342ba766 100644 (file)
@@ -110,12 +110,14 @@ struct solaris_x86_vtoc {
  * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
  * updated by Marc Espie <Marc.Espie@openbsd.org>
  */
-
 #define FREEBSD_PARTITION      0xa5    /* FreeBSD Partition ID */
 #define OPENBSD_PARTITION      0xa6    /* OpenBSD Partition ID */
 #define NETBSD_PARTITION       0xa9    /* NetBSD Partition ID */
 #define BSDI_PARTITION         0xb7    /* BSDI Partition ID */
 
+/* Ours is not to wonder why.. */
+#define BSD_PARTITION          FREEBSD_PARTITION
+
 /* check against BSD src/sys/sys/disklabel.h for consistency */
 
 #define BSD_DISKMAGIC  (0x82564557UL)  /* The disk magic number */
index 28f72e2559bff4a38e9867f3a4e4de1bb28ecd9b..0c7bd869923a471a0bc53aabeb79d60275efc90e 100644 (file)
@@ -166,10 +166,10 @@ static inline void reschedule_idle(struct task_struct * p)
 #ifdef __SMP__
        /*
         * ("wakeup()" should not be called before we've initialized
-        * SMP completely. [Linus, is there any exception to this?]
+        * SMP completely.
         * Basically a not-yet initialized SMP subsystem can be
         * considered as a not-yet working scheduler, simply dont use
-        * it before it'd up and running ...)
+        * it before it's up and running ...)
         *
         * SMP rescheduling is done in 2 passes:
         *  - pass #1: faster: 'quick decisions'
@@ -181,9 +181,10 @@ static inline void reschedule_idle(struct task_struct * p)
         *
         * There are two metrics here:
         *
-        * first, a 'cutoff' interval, currently ~250 usecs on
-        * x86 CPUs. If the current process has longer average
-        * timeslices than this, then we utilize the idle CPU.
+        * first, a 'cutoff' interval, currently 0-200 usecs on
+        * x86 CPUs, depending on the size of the 'SMP-local cache'.
+        * If the current process has longer average timeslices than
+        * this, then we utilize the idle CPU.
         *
         * second, if the wakeup comes from a process context,
         * then the two processes are 'related'. (they form a
@@ -308,8 +309,6 @@ static void process_timeout(unsigned long __data)
        wake_up_process(p);
 }
 
-int _PROC_CHANGE_PENALTY = 13;
-
 /*
  * This is the function that decides how desirable a process is..
  * You can weigh different processes against each other depending
index 7564d2ee117408e6ec238af6418a22d38aa012e3..498e4f63de1d024ac07c9b2bad638ada9dc77fb1 100644 (file)
@@ -41,7 +41,7 @@ static void rw_swap_page_base(int rw, unsigned long entry, struct page *page, in
        struct swap_info_struct * p;
        int zones[PAGE_SIZE/512];
        int zones_used;
-       kdev_t dev;
+       kdev_t dev = 0;
        int block_size;
 
 #ifdef DEBUG_SWAP
index 443daba5aaf9614dc9c09a81456fc88635105b30..02bcd39fbddf1904536b88111c93ab12f50cf1b8 100644 (file)
@@ -2284,7 +2284,6 @@ static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
 
                case SIOCIPXNCPCONN:
                 {
-                       int err;
                        /*
                         * This socket wants to take care of the NCP connection
                         * handed to us in arg.
index b04adbcaa74e0991b0d994c6500bb85d1a87697e..f5985e7512dd1161db469350e05b5bcbacabb7fd 100644 (file)
@@ -52,6 +52,8 @@
 #include <net/ax25.h>
 #include <net/netrom.h>
 
+#ifdef CONFIG_INET
+
 /*
  *     Only allow IP over NET/ROM frames through if the netrom device is up.
  */
@@ -81,37 +83,6 @@ int nr_rx_ip(struct sk_buff *skb, struct device *dev)
        return 1;
 }
 
-static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
-       void *daddr, void *saddr, unsigned len)
-{
-       unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
-
-       memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);
-       buff[6] &= ~AX25_CBIT;
-       buff[6] &= ~AX25_EBIT;
-       buff[6] |= AX25_SSSID_SPARE;
-       buff    += AX25_ADDR_LEN;
-
-       if (daddr != NULL)
-               memcpy(buff, daddr, dev->addr_len);
-       buff[6] &= ~AX25_CBIT;
-       buff[6] |= AX25_EBIT;
-       buff[6] |= AX25_SSSID_SPARE;
-       buff    += AX25_ADDR_LEN;
-
-       *buff++ = sysctl_netrom_network_ttl_initialiser;
-
-       *buff++ = NR_PROTO_IP;
-       *buff++ = NR_PROTO_IP;
-       *buff++ = 0;
-       *buff++ = 0;
-       *buff++ = NR_PROTOEXT;
-
-       if (daddr != NULL)
-               return 37;
-
-       return -37;
-}
 
 static int nr_rebuild_header(struct sk_buff *skb)
 {
@@ -121,10 +92,6 @@ static int nr_rebuild_header(struct sk_buff *skb)
        unsigned char *bp = skb->data;
 
        if (arp_find(bp + 7, skb)) {
-#if 0
-               /* BUGGGG! If arp_find returned 1, skb does not exist. --ANK*/
-               kfree_skb(skb);
-#endif
                return 1;
        }
 
@@ -158,6 +125,47 @@ static int nr_rebuild_header(struct sk_buff *skb)
        return 1;
 }
 
+#else
+
+static int nr_rebuild_header(struct sk_buff *skb)
+{
+       return 1;
+}
+
+#endif
+
+static int nr_header(struct sk_buff *skb, struct device *dev, unsigned short type,
+       void *daddr, void *saddr, unsigned len)
+{
+       unsigned char *buff = skb_push(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
+
+       memcpy(buff, (saddr != NULL) ? saddr : dev->dev_addr, dev->addr_len);
+       buff[6] &= ~AX25_CBIT;
+       buff[6] &= ~AX25_EBIT;
+       buff[6] |= AX25_SSSID_SPARE;
+       buff    += AX25_ADDR_LEN;
+
+       if (daddr != NULL)
+               memcpy(buff, daddr, dev->addr_len);
+       buff[6] &= ~AX25_CBIT;
+       buff[6] |= AX25_EBIT;
+       buff[6] |= AX25_SSSID_SPARE;
+       buff    += AX25_ADDR_LEN;
+
+       *buff++ = sysctl_netrom_network_ttl_initialiser;
+
+       *buff++ = NR_PROTO_IP;
+       *buff++ = NR_PROTO_IP;
+       *buff++ = 0;
+       *buff++ = 0;
+       *buff++ = NR_PROTOEXT;
+
+       if (daddr != NULL)
+               return 37;
+
+       return -37;
+}
+
 static int nr_set_mac_address(struct device *dev, void *addr)
 {
        struct sockaddr *sa = addr;
index 5be5c62efb36884d7a8fa26137d6b80c71f34a37..311dc7136315c17d5146c0d0ef2d1022fbcada54 100644 (file)
@@ -37,9 +37,9 @@
 #include <linux/kernel.h>
 #include <linux/module.h>      /* support for loadable modules */
 #include <linux/malloc.h>      /* kmalloc(), kfree() */
-#include <linux/vmalloc.h>      /* vmalloc(), vfree() */
 #include <linux/mm.h>          /* verify_area(), etc. */
 #include <linux/string.h>      /* inline mem*, str* functions */
+#include <linux/vmalloc.h>     /* vmalloc, vfree */
 #include <asm/segment.h>       /* kernel <-> user copy */
 #include <asm/byteorder.h>     /* htons(), etc. */
 #include <asm/uaccess.h>       /* copy_to/from_user */
@@ -104,7 +104,30 @@ static unsigned char oui_ether[] = { 0x00, 0x00, 0x00 };
 static unsigned char oui_802_2[] = { 0x00, 0x80, 0xC2 };
 #endif
 
-#ifdef MODULE
+#ifndef MODULE
+
+int wanrouter_init(void)
+{
+       int err;
+       extern void wanpipe_init(void);
+
+       printk(KERN_INFO "%s v%u.%u %s\n",
+               fullname, ROUTER_VERSION, ROUTER_RELEASE, copyright);
+       err = wanrouter_proc_init();
+       if (err)
+               printk(KERN_ERR "%s: can't create entry in proc filesystem!\n", modname);               
+
+       /*
+        *      Initialise compiled in boards
+        */             
+        
+#ifdef CONFIG_VENDOR_SANGOMA
+       wanpipe_init();
+#endif 
+       return err;
+}
+
+#else
 
 /*
  *     Kernel Loadable Module Entry Points
@@ -143,14 +166,6 @@ void cleanup_module (void)
        wanrouter_proc_cleanup();
 }
 
-#else
-
-__initfunc(void wanrouter_init(void))
-{
-       int err = wanrouter_proc_init();
-       if (err) printk(KERN_ERR
-               "%s: can't create entry in proc filesystem!\n", modname);
-}
 #endif
 
 /*
@@ -444,7 +459,7 @@ int wanrouter_ioctl(struct inode* inode, struct file* file,
 static int device_setup (wan_device_t* wandev, wandev_conf_t* u_conf)
 {
        void* data;
-       wandev_conf_tconf;
+       wandev_conf_t *conf;
        int err= -EINVAL;
 
        if (wandev->setup == NULL)      /* Nothing to do ? */
@@ -477,9 +492,13 @@ static int device_setup (wan_device_t* wandev, wandev_conf_t* u_conf)
                                err = wandev->setup(wandev,conf);
                        }
                        else 
-                               err = -ENOBUFS;
-                       vfree(data);
+                               err = -EFAULT;
                }
+               else
+                       err = -ENOBUFS;
+                       
+               if (data)
+                       vfree(data);
        }
 bail:
        kfree(conf);