Linux 2.4.0-test82.4.0-test8
authorLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:41 +0000 (23 15:38 -0500)
committerLinus Torvalds<torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:38:41 +0000 (23 15:38 -0500)
Ok, as the truncate problems really seem to be fixed, it's time to do an
official test8, the first development kernel in about a year and a half
that should have a working truncate() again. Thanks to everybody who
tested, and especially to Al Viro who did a lot of the heavy lifting.

There are a number of other various changes there too - the truncate fix
itself was fairly small, it was just more complex than most problems that
can be solved in 50 lines of code.

The only one of any note that I'd like to point out directly is the
clarification in the COPYING file, making it clear that it's only _that_
particular version of the GPL that is valid for the kernel. This should
not come as any surprise, as that's the same license that has been there
since 0.12 or so, but I thought I'd make that explicit.

Why? There's been some discussions of a GPL v3 which would limit licensing
to certain "well-behaved" parties, and I'm not sure I'd agree with such
restrictions - and the GPL itself allows for "any version" so I wanted to
make this part unambigious as far as my personal code is concerned.

The reason I wanted to mention that particular issue here explicitly
(rather than as just a one-liner in the changelog) is that code written by
others is obviously under _their_ discretion, and not limited by my
personal foibles, fears and misgivings.

If anybody wants to explicitly state that their code will be valid under
any version of the GPL (current or future - whatever they may look like),
please send patches to say so for the code in question. If you've used the
FSF boiler-place copyright notice, you already have this in place (it says
"v2 or later" - the FSF itself doesn't recommend v1 any more).

(Me, I'm taking the careful "wait and see" approach. I don't know if a GPL
v3 is imminent, and I don't know if the issues discussed will even
_become_ real issues, so you might as well consider me a paranoid, if
careful, bastard).

Linus

 - final:
    - sparc updates
    - routing cleanups
    - fix up warnings
    - USB: dsbr driver update and warning cleanup
    - USB: update the status file timestamps when changes occur
    - USB: clean up module init/exit. No more explicit inits.
    - USB: bluetooth and microtek driver updates
    - serial.c: remove duplicated code. Add SGI serial port signature.
    - /proc/kcore and ncpfs - more care with kernel virtual addresses
    - discontiguous memory initialization fixup
    - sd oom fixes
    - pcmcia state machine fixes.
    - microcode driver update - make sure we get a sane revision level
    - copyright license version clarification (make v2 explicit)
    - epic100, 8139too and tulip driver updates
    - clean up truncate_inode_pages (no, this has nothing to do with the
      rest of the truncate issues)
    - jffs update

93 files changed:
COPYING
CREDITS
Documentation/DMA-mapping.txt
Documentation/cachetlb.txt
Documentation/networking/8139too.txt
Documentation/networking/tulip.txt
arch/arm/mm/init.c
arch/i386/kernel/microcode.c
arch/i386/kernel/mpparse.c
arch/mips64/sgi-ip27/ip27-memory.c
arch/sh/mm/init.c
arch/sparc/kernel/Makefile
arch/sparc/kernel/entry.S
arch/sparc/kernel/irq.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/process.c
arch/sparc/kernel/setup.c
arch/sparc/kernel/signal.c
arch/sparc/kernel/smp.c
arch/sparc/kernel/solaris.c[deleted file]
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sun4m_smp.c
arch/sparc/kernel/sunos_ioctl.c
arch/sparc/kernel/sys_solaris.c
arch/sparc/kernel/traps.c
arch/sparc/mm/init.c
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/irq.c
arch/sparc64/kernel/pci.c
arch/sparc64/kernel/process.c
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/mm/init.c
arch/sparc64/solaris/signal.c
drivers/char/serial.c
drivers/net/8139too.c
drivers/net/epic100.c
drivers/net/sunhme.c
drivers/net/tulip/interrupt.c
drivers/net/tulip/tulip_core.c
drivers/pcmcia/cs.c
drivers/sbus/audio/dbri.c
drivers/sbus/char/Makefile
drivers/sbus/char/sab82532.c
drivers/sbus/char/su.c
drivers/sbus/char/vfc_dev.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/usb/bluetooth.c
drivers/usb/dabusb.c
drivers/usb/dsbr100.c
drivers/usb/inode.c
drivers/usb/microtek.c
drivers/usb/serial/whiteheat.c
drivers/usb/uhci.c
drivers/usb/usb-core.c
drivers/usb/usb-ohci.c
drivers/usb/usb-uhci.c
drivers/usb/uss720.c
fs/jffs/inode-v23.c
fs/jffs/intrep.c
fs/jffs/intrep.h
fs/jffs/jffs_fm.c
fs/jffs/jffs_fm.h
fs/ncpfs/dir.c
fs/proc/kcore.c
include/asm-i386/mpspec.h
include/asm-i386/spinlock.h
include/asm-sparc/atomic.h
include/asm-sparc/audioio.h
include/asm-sparc/floppy.h
include/asm-sparc/smp.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/netdevice.h
include/linux/smp.h
include/net/route.h
ipc/shm.c
kernel/ptrace.c
mm/filemap.c
mm/numa.c
mm/page_alloc.c
net/core/dev.c
net/ipv4/igmp.c
net/ipv4/ip_output.c
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/iptable_mangle.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c
net/netsyms.c

index c69cfd8..e84a688 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -6,6+6,10 @@
  Foundation, but the instance of code that it refers to (the Linux
  kernel) is copyrighted by me and others who actually wrote it.
 
+ Also note that the only valid version of the GPL as far as the kernel
+ is concerned is _this_ license (ie v2), unless explicitly otherwise
+ stated.
+
                        Linus Torvalds
 
 ----------------------------------------
index 3a2378a..9901b18 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -2126,6+2126,16 @@ S: 4390 Albany Drive #41A
 S: San Jose, California 95129
 S: USA
 
+N: Juan Quintela
+E: quintela@fi.udc.es
+D: Memory Management hacking
+S: LFCIA
+S: Departamento de Computación
+S: Universidade da Coruña
+S: E-15071
+S: A Coruña
+S: Spain
+
 N: Augusto Cesar Radtke
 E: bishop@sekure.org
 W: http://bishop.sekure.org
index 5dd11a1..0ffccde 100644 (file)
@@ -345,13+345,13 @@ to use the pci_dma_sync_*() interfaces.
                         * the DMA transfer with the CPU first
                         * so that we see updated contents.
                         */
-                       pci_dma_sync_single(cp->pdev, cp->rx_buf, cp->rx_len,
+                       pci_dma_sync_single(cp->pdev, cp->rx_dma, cp->rx_len,
                                            PCI_DMA_FROMDEVICE);
 
                        /* Now it is safe to examine the buffer. */
                        hp = (struct my_card_header *) cp->rx_buf;
                        if (header_is_ok(hp)) {
-                               pci_unmap_single(cp->pdev, cp->rx_buf, cp->rx_len,
+                               pci_unmap_single(cp->pdev, cp->rx_dma, cp->rx_len,
                                                 PCI_DMA_FROMDEVICE);
                                pass_to_upper_layers(cp->rx_buf);
                                make_and_setup_new_rx_buf(cp);
index 578dcb3..3d00346 100644 (file)
@@ -47,7+47,7 @@ changes occur:
 
        This interface is used to handle whole address space
        page table operations such as what happens during
-       fork, exit, and exec.
+       fork, and exec.
 
 3) void flush_tlb_range(struct mm_struct *mm,
                        unsigned long start, unsigned long end)
@@ -272,7+272,7 @@ Here is the new interface:
        for example, uses this technique.
 
        The "address" parameter tells the virtual address where the
-       user has this page mapped.
+       user will ultimately this page mapped.
 
        If D-cache aliasing is not an issue, these two routines may
        simply call memcpy/memset directly and do nothing more.
index f27811a..fc45638 100644 (file)
@@ -188,6+188,15 @@ User-mode (or maybe optional /proc) diagnostics program.
 
 Change History
 --------------
+Version 0.9.8 - September 7, 2000
+
+* Propagate request_irq error value (andrew morton)
+* Correct potential oops bug in PCI DMA unmap code
+* Fix bugs related to counting/discounting of 32-bit CRC in each Rx packet
+* Fix 16/32-bit bug in interrupt status check
+* Timer cleanups (andrew morton)
+
+
 Version 0.9.7 - June 11, 2000
 
 * Fix support for older chips (RTL8139 early chips should now work again)
index b5a6254..5363811 100644 (file)
@@ -142,6+142,13 @@ tulip_core.c       - Driver core (a.k.a. where "everything else" goes)
 
 Version history
 ===============
+0.9.10 (September 6, 2000):
+* Simple interrupt mitigation (via jamal)
+* More PCI ids
+
+0.9.9 (August 11, 2000):
+* More PCI ids
+
 0.9.8 (July 13, 2000):
 * Correct signed/unsigned comparison for dummy frame index
 * Remove outdated references to struct enet_statistics
index ba58e8b..c66dd36 100644 (file)
@@ -528,7+528,7 @@ void __init paging_init(struct meminfo *mi)
                        zhole_size[0] -= mi->bank[i].size >> PAGE_SHIFT;
                }
 
-               free_area_init_node(node, pgdat, zone_size,
+               free_area_init_node(node, pgdat, 0, zone_size,
                                bdata->node_boot_start, zhole_size);
        }
 
index 1d5b7b3..80536a1 100644 (file)
  *             Removed ->release(). Removed exclusive open and status bitmap.
  *             Added microcode_rwsem to serialize read()/write()/ioctl().
  *             Removed global kernel lock usage.
+ *     1.07    07 Sep 2000, Tigran Aivazian <tigran@veritas.com>
+ *             Write 0 to 0x8B msr and then cpuid before reading revision,
+ *             so that it works even if there were no update done by the
+ *             BIOS. Otherwise, reading from 0x8B gives junk (which happened
+ *             to be 0 on my machine which is why it worked even when I
+ *             disabled update by the BIOS)
+ *             Thanks to Eric W. Biederman <ebiederman@lnxi.com> for the fix.
  */
 
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/processor.h>
 
-#define MICROCODE_VERSION      "1.06"
+#define MICROCODE_VERSION      "1.07"
 
 MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@veritas.com>");
@@ -188,7+195,8 @@ static void do_update_one(void *unused)
                    microcode[i].ldrver == 1 && microcode[i].hdrver == 1) {
 
                        found=1;
-
+                       wrmsr(0x8B, 0, 0);
+                       __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx");
                        rdmsr(0x8B, val[0], rev);
                        if (microcode[i].rev <= rev) {
                                printk(KERN_ERR 
index 746bea0..66b70a8 100644 (file)
@@ -35,7+35,7 @@ int smp_found_config = 0;
  * MP-table.
  */
 int apic_version [MAX_APICS];
-int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+int mp_bus_id_to_type [MAX_MP_BUSSES];
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
 int mp_current_pci_id = 0;
 int pic_mode;
@@ -158,19+158,18 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
        str[6] = 0;
        Dprintk("Bus #%d is %s\n", m->mpc_busid, str);
 
-       if (strncmp(str, "ISA", 3) == 0) {
+       if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
-       } else if (strncmp(str, "EISA", 4) == 0) {
+       } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_EISA;
-       } else if (strncmp(str, "PCI", 3) == 0) {
+       } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_PCI;
                mp_bus_id_to_pci_bus[m->mpc_busid] = mp_current_pci_id;
                mp_current_pci_id++;
-       } else if (strncmp(str, "MCA", 3) == 0) {
+       } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
                mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
        } else {
-               printk("Unknown bustype %s\n", str);
-               panic("cannot handle bus - mail to linux-smp@vger.kernel.org");
+               printk("Unknown bustype %s - ignoring\n", str);
        }
 }
 
index c31e006..50e0341 100644 (file)
@@ -242,7+242,7 @@ void __init paging_init(void)
                pfn_t end_pfn = node_getmaxclick(node);
 
                zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn;
-               free_area_init_node(node, NODE_DATA(node), zones_size, 
+               free_area_init_node(node, NODE_DATA(node), 0, zones_size, 
                                                start_pfn << PAGE_SHIFT, 0);
                if ((PLAT_NODE_DATA_STARTNR(node) + 
                                        PLAT_NODE_DATA_SIZE(node)) > pagenr)
index 5e0632a..ccabeb8 100644 (file)
@@ -227,7+227,7 @@ void __init paging_init(void)
                        zones_size[ZONE_DMA] = max_dma - start_pfn;
                        zones_size[ZONE_NORMAL] = low - max_dma;
                }
-               free_area_init_node(0, 0, zones_size, __MEMORY_START, 0);
+               free_area_init_node(0, 0, 0, zones_size, __MEMORY_START, 0);
        }
 }
 
index c8c7959..d57c23c 100644 (file)
@@ -1,4+1,4 @@
-# $Id: Makefile,v 1.60 2000/08/12 08:35:53 ecd Exp $
+# $Id: Makefile,v 1.61 2000/09/03 13:58:04 anton Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -22,7+22,7 @@ IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o
 O_OBJS   := entry.o wof.o wuf.o etrap.o rtrap.o traps.o ${IRQ_OBJS} \
            process.o signal.o ioport.o setup.o idprom.o \
            sys_sparc.o sunos_asm.o sparc-stub.o systbls.o \
-           time.o windows.o cpu.o devices.o sclow.o solaris.o \
+           time.o windows.o cpu.o devices.o sclow.o \
            tadpole.o tick14.o ptrace.o sys_solaris.o \
            unaligned.o muldiv.o pcic.o semaphore.o
 
index cd2f373..c44fe31 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: entry.S,v 1.166 2000/06/19 06:24:36 davem Exp $
+/* $Id: entry.S,v 1.167 2000/09/06 00:45:00 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
index a088424..eaa7fc4 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: irq.c,v 1.107 2000/08/26 02:42:28 anton Exp $
+/*  $Id: irq.c,v 1.109 2000/08/31 10:00:39 anton Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -197,7+197,7 @@ void free_irq(unsigned int irq, void *dev_id)
 
 #ifdef CONFIG_SMP
 
-/* Who has global_irq_lock. */
+/* Who has the global irq brlock */
 unsigned char global_irq_holder = NO_PROC_ID;
 
 void smp_show_backtrace_all_cpus(void);
@@ -329,7+329,8 @@ void __global_sti(void)
  */
 unsigned long __global_save_flags(void)
 {
-       unsigned long flags, local_enabled, retval;
+       unsigned long flags, retval;
+       unsigned long local_enabled = 0;
 
        __save_flags(flags);
 
index d5ce703..293cf43 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: pcic.c,v 1.16 2000/07/11 01:38:57 davem Exp $
+/* $Id: pcic.c,v 1.17 2000/09/05 06:49:44 anton Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -940,7+940,6 @@ asmlinkage int sys_pciconfig_read(unsigned long bus,
        if(!suser())
                return -EPERM;
 
-       lock_kernel();
        switch(len) {
        case 1:
                pcibios_read_config_byte(bus, dfn, off, &ubyte);
@@ -959,7+958,6 @@ asmlinkage int sys_pciconfig_read(unsigned long bus,
                err = -EINVAL;
                break;
        };
-       unlock_kernel();
 
        return err;
 }
index f730f85..fe45f1f 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: process.c,v 1.151 2000/07/11 23:22:17 davem Exp $
+/*  $Id: process.c,v 1.153 2000/09/06 00:45:01 davem Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -234,7+234,6 @@ void show_backtrace(void)
 void smp_show_backtrace_all_cpus(void)
 {
        xc0((smpfunc_t) show_backtrace);
-       show_backtrace();
 }
 #endif
 
index 5398a93..bce4ffc 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: setup.c,v 1.118 2000/05/09 17:40:13 davem Exp $
+/*  $Id: setup.c,v 1.119 2000/08/31 10:24:17 anton Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
@@ -80,12+80,7 @@ void prom_sync_me(void)
 {
        unsigned long prom_tbr, flags;
 
-#ifdef CONFIG_SMP
-       global_irq_holder = NO_PROC_ID;
-       *((unsigned char *)&global_irq_lock) = 0;
-       *((unsigned char *)&global_bh_lock) = 0;
-#endif
-       __save_and_cli(flags);
+       save_and_cli(flags);
        __asm__ __volatile__("rd %%tbr, %0\n\t" : "=r" (prom_tbr));
        __asm__ __volatile__("wr %0, 0x0, %%tbr\n\t"
                             "nop\n\t"
@@ -99,9+94,9 @@ void prom_sync_me(void)
        prom_printf("PROM SYNC COMMAND...\n");
        show_free_areas();
        if(current->pid != 0) {
-               __sti();
+               sti();
                sys_sync();
-               __cli();
+               cli();
        }
        prom_printf("Returning to prom\n");
 
@@ -109,7+104,7 @@ void prom_sync_me(void)
                             "nop\n\t"
                             "nop\n\t"
                             "nop\n\t" : : "r" (prom_tbr));
-       __restore_flags(flags);
+       restore_flags(flags);
 
        return;
 }
index 012d19e..6ac8c4b 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: signal.c,v 1.106 2000/07/07 04:25:17 davem Exp $
+/*  $Id: signal.c,v 1.107 2000/09/05 21:44:54 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
index 677b2c8..0e19444 100644 (file)
@@ -145,35+145,33 @@ void __init smp_boot_cpus(void)
 void smp_flush_cache_all(void)
 {
        xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all));
-       local_flush_cache_all();
 }
 
 void smp_flush_tlb_all(void)
 {
        xc0((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_all));
-       local_flush_tlb_all();
 }
 
 void smp_flush_cache_mm(struct mm_struct *mm)
 {
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+               if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+                       local_flush_cache_mm(mm);
+               else
                        xc1((smpfunc_t) BTFIXUP_CALL(local_flush_cache_mm), (unsigned long) mm);
-
-               local_flush_cache_mm(mm);
        }
 }
 
 void smp_flush_tlb_mm(struct mm_struct *mm)
 {
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id())) {
+               if(mm->cpu_vm_mask == (1 << smp_processor_id())) {
+                       local_flush_tlb_mm(mm);
+               } else {
                        xc1((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_mm), (unsigned long) mm);
                        if(atomic_read(&mm->mm_users) == 1 && current->active_mm == mm)
                                mm->cpu_vm_mask = (1 << smp_processor_id());
                }
-
-               local_flush_tlb_mm(mm);
        }
 }
 
@@ -181,10+179,10 @@ void smp_flush_cache_range(struct mm_struct *mm, unsigned long start,
                           unsigned long end)
 {
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+               if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+                       local_flush_cache_range(mm, start, end);
+               else
                        xc3((smpfunc_t) BTFIXUP_CALL(local_flush_cache_range), (unsigned long) mm, start, end);
-
-               local_flush_cache_range(mm, start, end);
        }
 }
 
@@ -192,10+190,10 @@ void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
                         unsigned long end)
 {
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+               if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+                               local_flush_tlb_range(mm, start, end);
+               else
                        xc3((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_range), (unsigned long) mm, start, end);
-
-               local_flush_tlb_range(mm, start, end);
        }
 }
 
@@ -204,10+202,10 @@ void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
        struct mm_struct *mm = vma->vm_mm;
 
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+               if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+                       local_flush_cache_page(vma, page);
+               else
                        xc2((smpfunc_t) BTFIXUP_CALL(local_flush_cache_page), (unsigned long) vma, page);
-
-               local_flush_cache_page(vma, page);
        }
 }
 
@@ -216,10+214,10 @@ void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
        struct mm_struct *mm = vma->vm_mm;
 
        if(mm->context != NO_CONTEXT) {
-               if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+               if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+                       local_flush_tlb_page(vma, page);
+               else
                        xc2((smpfunc_t) BTFIXUP_CALL(local_flush_tlb_page), (unsigned long) vma, page);
-
-               local_flush_tlb_page(vma, page);
        }
 }
 
@@ -233,7+231,6 @@ void smp_flush_page_to_ram(unsigned long page)
         */
 #if 1
        xc1((smpfunc_t) BTFIXUP_CALL(local_flush_page_to_ram), page);
-       local_flush_page_to_ram(page);
 #else
        local_flush_page_to_ram(page);
 #endif
@@ -241,10+238,10 @@ void smp_flush_page_to_ram(unsigned long page)
 
 void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr)
 {
-       if(mm->cpu_vm_mask != (1 << smp_processor_id()))
+       if(mm->cpu_vm_mask == (1 << smp_processor_id()))
+               local_flush_sig_insns(mm, insn_addr);
+       else
                xc2((smpfunc_t) BTFIXUP_CALL(local_flush_sig_insns), (unsigned long) mm, insn_addr);
-
-       local_flush_sig_insns(mm, insn_addr);
 }
 
 /* Reschedule call back. */
diff --git a/arch/sparc/kernel/solaris.c b/arch/sparc/kernel/solaris.c
deleted file mode 100644 (file)
index bcebd92..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* solaris.c: Solaris binary emulation, whee...
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-
-#include <asm/errno.h>
-#include <asm/solerrno.h>
-
-asmlinkage int solaris_open(const char *filename, int flags, int mode)
-{
-       int newflags;
-       int ret;
-
-       lock_kernel();
-       newflags = flags & 0xf;
-       flags &= ~0xf;
-       if(flags & 0x8050)
-               newflags |= FASYNC;
-       if(flags & 0x80)
-               newflags |= O_NONBLOCK;
-       if(flags & 0x100)
-               newflags |= O_CREAT;
-       if(flags & 0x200)
-               newflags |= O_TRUNC;
-       if(flags & 0x400)
-               newflags |= O_EXCL;
-       if(flags & 0x800)
-               newflags |= O_NOCTTY;
-       ret = sys_open(filename, newflags, mode);
-       unlock_kernel();
-       return ret;
-}
index a1742c2..997e4d0 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: sparc_ksyms.c,v 1.103 2000/08/26 02:42:28 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.104 2000/09/06 05:43:00 anton Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -141,6+141,11 @@ EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_save_flags);
 EXPORT_SYMBOL(__global_restore_flags);
+
+/* Misc SMP information */
+EXPORT_SYMBOL(smp_num_cpus);
+EXPORT_SYMBOL(__cpu_number_map);
+EXPORT_SYMBOL(__cpu_logical_map);
 #endif
 
 EXPORT_SYMBOL(udelay);
index 2803926..3a4e93e 100644 (file)
@@ -376,6+376,9 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                        }
                }
 
+               /* First, run local copy. */
+               func(arg1, arg2, arg3, arg4, arg5);  
+
                {
                        register int i;
 
@@ -393,6+396,8 @@ void smp4d_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                }
 
                spin_unlock_irqrestore(&cross_call_lock, flags);
+       } else {
+               func(arg1, arg2, arg3, arg4, arg5); /* Just need to run local copy. */
        }
 }
 
index d6c126d..52c37f5 100644 (file)
@@ -405,6+405,9 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                        }
                }
 
+               /* First, run local copy. */
+               func(arg1, arg2, arg3, arg4, arg5);  
+
                {
                        register int i;
 
@@ -422,6+425,8 @@ void smp4m_cross_call(smpfunc_t func, unsigned long arg1, unsigned long arg2,
                }
 
                spin_unlock_irqrestore(&cross_call_lock, flags);
+       } else {
+               func(arg1, arg2, arg3, arg4, arg5); /* Just need to run local copy. */
        }
 }
 
index dc26d2c..61df3ea 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: sunos_ioctl.c,v 1.33 1999/07/28 12:59:03 anton Exp $
+/* $Id: sunos_ioctl.c,v 1.34 2000/09/03 14:10:56 anton Exp $
  * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility.
  * 
  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -39,7+39,6 @@ asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
 {
        int ret = -EBADF;
 
-       lock_kernel();
        if (fd >= SUNOS_NR_OPEN || !fcheck(fd))
                goto out;
 
@@ -227,7+226,6 @@ asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg)
        /* so stupid... */
        ret = (ret == -EINVAL ? -EOPNOTSUPP : ret);
 out:
-       unlock_kernel();
        return ret;
 }
 
index d099c4e..fb75785 100644 (file)
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 
-/* CHECKME: this stuff looks rather bogus */
 asmlinkage int
 do_solaris_syscall (struct pt_regs *regs)
 {
-       int ret;
-
-       lock_kernel();
-       set_personality(PER_SVR4);
-
-       if (current->exec_domain && current->exec_domain->handler){
-               current->exec_domain->handler (0, regs);
-
-               /* What is going on here?  Why do we do this? */
-
-               /* XXX current->exec_domain->use_count = 0; XXX */
-
-               ret = regs->u_regs [UREG_I0];
-       } else {
-               printk ("No solaris handler\n");
-               send_sig (SIGSEGV, current, 1);
-               ret = 0;
-       }
-       unlock_kernel();
-       return ret;
+       static int cnt = 0;
+       if (++cnt < 10) printk ("No solaris handler\n");
+       force_sig(SIGSEGV, current);
+       return 0;
 }
 
 #ifndef CONFIG_SUNOS_EMUL
@@ -48,9+31,7 @@ do_sunos_syscall (struct pt_regs *regs)
 {
        static int cnt = 0;
        if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n");
-       lock_kernel();
        force_sig (SIGSEGV, current);
-       unlock_kernel();
        return 0;
 }
 #endif
index 3564a45..5c361f9 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: traps.c,v 1.63 2000/06/04 06:23:52 anton Exp $
+/* $Id: traps.c,v 1.64 2000/09/03 15:00:49 anton Exp $
  * arch/sparc/kernel/traps.c
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -132,7+132,6 @@ void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
 {
        siginfo_t info;
 
-       lock_kernel();
        if(type < 0x80) {
                /* Sun OS's puke from bad traps, Linux survives! */
                printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
@@ -148,7+147,6 @@ void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
        info.si_addr = (void *)pc;
        info.si_trapno = type - 0x80;
        force_sig_info(SIGILL, &info, current);
-       unlock_kernel();
 }
 
 void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -156,7+154,6 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
 {
        siginfo_t info;
 
-       lock_kernel();
        if(psr & PSR_PS)
                die_if_kernel("Kernel illegal instruction", regs);
 #ifdef TRAP_DEBUG
@@ -166,7+163,7 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
        if (sparc_cpu_model == sun4c || sparc_cpu_model == sun4) {
                extern int do_user_muldiv (struct pt_regs *, unsigned long);
                if (!do_user_muldiv (regs, pc))
-                       goto out;
+                       return;
        }
        info.si_signo = SIGILL;
        info.si_errno = 0;
@@ -174,8+171,6 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGILL, &info, current);
-out:
-       unlock_kernel();
 }
 
 void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -183,7+178,6 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
 {
        siginfo_t info;
 
-       lock_kernel();
        if(psr & PSR_PS)
                die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
        info.si_signo = SIGILL;
@@ -192,7+186,6 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGILL, &info, current);
-       unlock_kernel();
 }
 
 /* XXX User may want to be allowed to do this. XXX */
@@ -202,7+195,6 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon
 {
        siginfo_t info;
 
-       lock_kernel();
        if(regs->psr & PSR_PS) {
                printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
                       regs->u_regs[UREG_RETPC]);
@@ -220,7+212,6 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon
        info.si_addr = /* FIXME: Should dig out mna address */ (void *)0;
        info.si_trapno = 0;
        send_sig_info(SIGBUS, &info, current);
-       unlock_kernel();
 }
 
 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
@@ -237,7+228,6 @@ static unsigned long init_fregs[32] __attribute__ ((aligned (8))) =
 void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
                 unsigned long psr)
 {
-       lock_kernel();
        /* Sanity check... */
        if(psr & PSR_PS)
                die_if_kernel("Kernel gets FloatingPenguinUnit disabled trap", regs);
@@ -246,7+236,7 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
        regs->psr |= PSR_EF;
 #ifndef CONFIG_SMP
        if(last_task_used_math == current)
-               goto out;
+               return;
        if(last_task_used_math) {
                /* Other processes fpu state, save away */
                struct task_struct *fptask = last_task_used_math;
@@ -270,10+260,6 @@ void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
        }
        current->flags |= PF_USEDFPU;
 #endif
-#ifndef CONFIG_SMP
-out:
-#endif
-       unlock_kernel();
 }
 
 static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
@@ -295,7+281,6 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 #else
        struct task_struct *fpt = current;
 #endif
-       lock_kernel();
        put_psr(get_psr() | PSR_EF);
        /* If nobody owns the fpu right now, just clear the
         * error into our fake static buffer and hope it don't
@@ -308,7+293,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 #endif
                fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
                regs->psr &= ~PSR_EF;
-               goto out;
+               return;
        }
        fpsave(&fpt->thread.float_regs[0], &fpt->thread.fsr,
               &fpt->thread.fpqueue[0], &fpt->thread.fpqdepth);
@@ -361,7+346,7 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
                if(calls > 2)
                        die_if_kernel("Too many Penguin-FPU traps from kernel mode",
                                      regs);
-               goto out;
+               return;
        }
 
        fsr = fpt->thread.fsr;
@@ -389,8+374,6 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
        regs->psr &= ~PSR_EF;
        if(calls > 0)
                calls=0;
-out:
-       unlock_kernel();
 }
 
 void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -398,7+381,6 @@ void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long n
 {
        siginfo_t info;
 
-       lock_kernel();
        if(psr & PSR_PS)
                die_if_kernel("Penguin overflow trap from kernel mode", regs);
        info.si_signo = SIGEMT;
@@ -407,13+389,11 @@ void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long n
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGEMT, &info, current);
-       unlock_kernel();
 }
 
 void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
                       unsigned long psr)
 {
-       lock_kernel();
 #ifdef TRAP_DEBUG
        printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
               pc, npc, psr);
@@ -421,7+401,6 @@ void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc
        if(psr & PSR_PS)
                panic("Tell me what a watchpoint trap is, and I'll then deal "
                      "with such a beast...");
-       unlock_kernel();
 }
 
 void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -429,7+408,6 @@ void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc
 {
        siginfo_t info;
 
-       lock_kernel();
 #ifdef TRAP_DEBUG
        printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
               pc, npc, psr);
@@ -440,7+418,6 @@ void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        force_sig_info(SIGBUS, &info, current);
-       unlock_kernel();
 }
 
 void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -448,14+425,12 @@ void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long np
 {
        siginfo_t info;
 
-       lock_kernel();
        info.si_signo = SIGILL;
        info.si_errno = 0;
        info.si_code = ILL_COPROC;
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGILL, &info, current);
-       unlock_kernel();
 }
 
 void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -463,7+438,6 @@ void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long n
 {
        siginfo_t info;
 
-       lock_kernel();
 #ifdef TRAP_DEBUG
        printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
               pc, npc, psr);
@@ -474,7+448,6 @@ void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long n
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGILL, &info, current);
-       unlock_kernel();
 }
 
 void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
@@ -482,15+455,12 @@ void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc
 {
        siginfo_t info;
 
-       lock_kernel();
        info.si_signo = SIGFPE;
        info.si_errno = 0;
        info.si_code = FPE_INTDIV;
        info.si_addr = (void *)pc;
        info.si_trapno = 0;
        send_sig_info(SIGFPE, &info, current);
-
-       unlock_kernel();
 }
 
 /* Since we have our mappings set up, on multiprocessors we can spin them
index b323cca..642c986 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: init.c,v 1.91 2000/08/09 23:10:19 anton Exp $
+/*  $Id: init.c,v 1.93 2000/08/31 11:40:55 anton Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -89,8+89,6 @@ pgprot_t kmap_prot;
 
 void __init kmap_init(void)
 {
-       unsigned long pteval;
-
        /* cache the first kmap pte */
        kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN);
        kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
@@ -583,6+581,6 @@ void flush_page_to_ram(struct page *page)
 {
        unsigned long vaddr;
        vaddr = kmap(page);
-       __flush_page_to_ram(page_address(page));
+       __flush_page_to_ram((unsigned long)page_address(page));
        kunmap(page);
 }
index 9d946df..f453562 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: entry.S,v 1.118 2000/08/01 00:11:31 davem Exp $
+/* $Id: entry.S,v 1.119 2000/09/06 00:45:01 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
index 9e1c652..daefe6d 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: irq.c,v 1.92 2000/08/26 02:42:28 anton Exp $
+/* $Id: irq.c,v 1.93 2000/08/31 10:00:39 anton Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -550,7+550,7 @@ out:
 
 #ifdef CONFIG_SMP
 
-/* Who has global_irq_lock. */
+/* Who has the global irq brlock */
 unsigned char global_irq_holder = NO_PROC_ID;
 
 static void show(char * str)
index cd28d93..8af0c0f 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: pci.c,v 1.16 2000/03/01 02:53:33 davem Exp $
+/* $Id: pci.c,v 1.17 2000/09/05 06:49:44 anton Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -274,7+274,6 @@ asmlinkage int sys_pciconfig_read(unsigned long bus,
                goto out;
        }
 
-       lock_kernel();
        switch(len) {
        case 1:
                pci_read_config_byte(dev, off, &byte);
@@ -293,7+292,6 @@ asmlinkage int sys_pciconfig_read(unsigned long bus,
                err = -EINVAL;
                break;
        };
-       unlock_kernel();
 out:
        return err;
 }
index 82679ee..1f3386d 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: process.c,v 1.111 2000/08/16 11:13:12 davem Exp $
+/*  $Id: process.c,v 1.112 2000/09/06 00:45:01 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
index 043524e..c2a7833 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: signal.c,v 1.53 2000/07/30 23:12:24 davem Exp $
+/*  $Id: signal.c,v 1.54 2000/09/05 21:44:54 davem Exp $
  *  arch/sparc64/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
index 51b1e41..6d06328 100644 (file)
@@ -1,4+1,4 @@
-/*  $Id: signal32.c,v 1.66 2000/07/27 01:05:15 davem Exp $
+/*  $Id: signal32.c,v 1.67 2000/09/05 21:44:54 davem Exp $
  *  arch/sparc64/kernel/signal32.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
index 7eef978..deca034 100644 (file)
@@ -1029,7+1029,7 @@ void __init paging_init(void)
                zones_size[ZONE_DMA] = npages;
                zholes_size[ZONE_DMA] = npages - pages_avail;
 
-               free_area_init_node(0, NULL, zones_size,
+               free_area_init_node(0, NULL, NULL, zones_size,
                                    phys_base, zholes_size);
        }
 
index d7de503..8a6ecd9 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: signal.c,v 1.6 2000/08/29 07:01:54 davem Exp $
+/* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $
  * signal.c: Signal emulation for Solaris
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
index f23f911..7b11c8f 100644 (file)
@@ -4560,6+4560,9 @@ static struct pci_board pci_boards[] __initdata = {
        {       PCI_VENDOR_ID_ROCKWELL, 0x1004,
                0x1048, 0x1500, 
                SPCI_FL_BASE1, 1, 115200 },
+       {       PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
+               0xFF00, 0, SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE,
+               1, 458333, 0, 0, 0, 0x20178 },
 #if CONFIG_DDB5074
        /*
         * NEC Vrc-5074 (Nile 4) builtin UART.
@@ -5282,12+5285,6 @@ int register_serial(struct serial_struct *req)
                        break;
        }
        if (i == NR_PORTS) {
-               for (i = 4; i < NR_PORTS; i++)
-                       if ((rs_table[i].type == PORT_UNKNOWN) &&
-                           (rs_table[i].count == 0))
-                               break;
-       }
-       if (i == NR_PORTS) {
                for (i = 0; i < NR_PORTS; i++)
                        if ((rs_table[i].type == PORT_UNKNOWN) &&
                            (rs_table[i].count == 0))
index 6d06b0a..ff96f71 100644 (file)
@@ -97,7+97,7 @@ an MMIO register read.
 #include <asm/io.h>
 
 
-#define RTL8139_VERSION "0.9.7"
+#define RTL8139_VERSION "0.9.8"
 #define RTL8139_MODULE_NAME "8139too"
 #define RTL8139_DRIVER_NAME   RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
 #define PFX RTL8139_MODULE_NAME ": "
@@ -1061,6+1061,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
 static int rtl8139_open (struct net_device *dev)
 {
        struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv;
+       int retval;
 #ifdef RTL8139_DEBUG
        void *ioaddr = tp->mmio_addr;
 #endif
@@ -1069,10+1070,11 @@ static int rtl8139_open (struct net_device *dev)
 
        MOD_INC_USE_COUNT;
 
-       if (request_irq (dev->irq, &rtl8139_interrupt, SA_SHIRQ, dev->name, dev)) {
-               DPRINTK ("EXIT, returning -EBUSY\n");
+       retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
+       if (retval) {
+               DPRINTK ("EXIT, returning %d\n", retval);
                MOD_DEC_USE_COUNT;
-               return -EBUSY;
+               return retval;
        }
 
        tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
@@ -1339,7+1341,6 @@ static void rtl8139_timer (unsigned long data)
 
        mii_reg5 = mdio_read (dev, tp->phys[0], 5);
 
-#if 0
        if (!tp->duplex_lock && mii_reg5 != 0xffff) {
                void *ioaddr = tp->mmio_addr;
                int duplex = (mii_reg5 & 0x0100)
@@ -1356,7+1357,6 @@ static void rtl8139_timer (unsigned long data)
                        RTL_W8 (Cfg9346, Cfg9346_Lock);
                }
        }
-#endif
 
        rtl8139_tune_twister (dev, tp);
 
@@ -1417,15+1417,15 @@ static void rtl8139_tx_timeout (struct net_device *dev)
        /* Dump the unsent Tx packets. */
        for (i = 0; i < NUM_TX_DESC; i++) {
                struct ring_info *rp = &tp->tx_info[i];
+               if (rp->mapping != 0) {
+                       pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len, PCI_DMA_TODEVICE);
+                       rp->mapping = 0;
+               }
                if (rp->skb) {
                        dev_kfree_skb (rp->skb);
                        rp->skb = NULL;
                        tp->stats.tx_dropped++;
                }
-               if (rp->mapping != 0) {
-                       pci_unmap_single (tp->pci_dev, rp->mapping, rp->skb->len, PCI_DMA_TODEVICE);
-                       rp->mapping = 0;
-               }
        }
        
        spin_unlock_irq (&tp->lock);
@@ -1527,7+1527,13 @@ static inline void rtl8139_tx_interrupt (struct net_device *dev,
                }
 
                /* Free the original skb. */
-               dev_kfree_skb_irq (tp->tx_info[entry].skb);
+               if (tp->tx_info[entry].mapping != 0) {
+                       pci_unmap_single(tp->pci_dev,
+                                        tp->tx_info[entry].mapping,
+                                        tp->tx_info[entry].skb->len,
+                                        PCI_DMA_TODEVICE);
+                       tp->tx_info[entry].mapping = 0;
+               }                                                                                                                       dev_kfree_skb_irq (tp->tx_info[entry].skb);
                tp->tx_info[entry].skb = NULL;
                dirty_tx++;
                if (netif_queue_stopped (dev) &&
@@ -1575,8+1581,7 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
 
        while ((RTL_R8 (ChipCmd) & RxBufEmpty) == 0) {
                int ring_offset = cur_rx % RX_BUF_LEN;
-               u32 rx_status =
-                   le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+               u32 rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
                int rx_size = rx_status >> 16;
 
                DPRINTK ("%s:  rtl8139_rx() status %4.4x, size %4.4x,"
@@ -1654,11+1659,12 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
                        /* Malloc up new buffer, compatible with net-2e. */
                        /* Omit the four octet CRC from the length. */
                        struct sk_buff *skb;
+                       int pkt_size = rx_size - 4;
 
-                       skb = dev_alloc_skb (rx_size + 2);
+                       skb = dev_alloc_skb (pkt_size + 2);
                        if (skb == NULL) {
                                printk (KERN_WARNING
-                                       "%s: Memory squeeze, deferring packet.\n",
+                                       "%s: Memory squeeze, dropping packet.\n",
                                        dev->name);
                                /* We should check that some rx space is free.
                                   If not, free one and mark stats->rx_dropped++. */
@@ -1675,8+1681,8 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
                                memcpy (skb_put (skb, semi_count),
                                        &rx_ring[ring_offset + 4],
                                        semi_count);
-                               memcpy (skb_put (skb, rx_size - semi_count),
-                                       rx_ring, rx_size - semi_count);
+                               memcpy (skb_put (skb, pkt_size - semi_count),
+                                       rx_ring, pkt_size - semi_count);
 #ifdef RTL8139_DEBUG
                                {
                                int i;
@@ -1692,12+1698,12 @@ static void rtl8139_rx_interrupt (struct net_device *dev,
                        } else {
                                eth_copy_and_sum (skb,
                                                  &rx_ring[ring_offset + 4],
-                                                 rx_size - 4, 0);
-                               skb_put (skb, rx_size - 4);
+                                                 pkt_size, 0);
+                               skb_put (skb, pkt_size);
                        }
                        skb->protocol = eth_type_trans (skb, dev);
                        netif_rx (skb);
-                       tp->stats.rx_bytes += rx_size;
+                       tp->stats.rx_bytes += pkt_size;
                        tp->stats.rx_packets++;
                }
 
@@ -1784,7+1790,7 @@ static void rtl8139_interrupt (int irq, void *dev_instance,
                status = RTL_R16 (IntrStatus);
 
                /* h/w no longer present (hotplug?) or major error, bail */
-               if (status == 0xFFFFFFFF)
+               if (status == 0xFFFF)
                        break;
                
                /* Acknowledge all of the current interrupt sources ASAP, but
@@ -1868,6+1874,8 @@ static int rtl8139_close (struct net_device *dev)
        DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
                        dev->name, RTL_R16 (IntrStatus));
 
+       del_timer_sync (&tp->timer);
+       
        spin_lock_irqsave (&tp->lock, flags);
 
        /* Disable interrupts by clearing the interrupt mask. */
@@ -1882,8+1890,6 @@ static int rtl8139_close (struct net_device *dev)
 
        spin_unlock_irqrestore (&tp->lock, flags);
        
-       del_timer (&tp->timer);
-       
        /* snooze for a small bit */
        if (current->need_resched)
                schedule ();
index bdf5a48..e55e83e 100644 (file)
        LK1.1.4 (jgarzik):
        * Merge becker test version 1.09 (5/29/2000)
 
+       LK1.1.5 (jgarzik):
+       * Fix locking
+       * Limit 83c175 probe to ethernet-class PCI devices
+
 */
 
 /* These identify the driver base version and may not be removed. */
@@ -41,7+45,7 @@ static const char version[] =
 static const char version2[] =
 "  http://www.scyld.com/network/epic100.html\n";
 static const char version3[] =
-" (unofficial 2.4.x kernel port, version 1.1.4, August 10, 2000)\n";
+" (unofficial 2.4.x kernel port, version 1.1.5, September 7, 2000)\n";
 
 /* The user-configurable values.
    These may be modified when a driver module is loaded.*/
@@ -489,13+493,11 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
 
        return 0;
 
-err_out_iounmap:
 #ifndef USE_IO_OPS
-       iounmap ((void*) ioaddr);
 err_out_free_mmio:
-#endif
        release_mem_region (pci_resource_start (pdev, 1),
                            pci_resource_len (pdev, 1));
+#endif
 err_out_free_pio:
        release_region (pci_resource_start (pdev, 0),
                        pci_resource_len (pdev, 0));
index 23ba505..44a759c 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: sunhme.c,v 1.96 2000/06/09 07:35:27 davem Exp $
+/* $Id: sunhme.c,v 1.97 2000/09/05 23:12:36 davem Exp $
  * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -2759,7+2759,7 @@ static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pd
        }               
 
        hpreg_base = pci_resource_start(pdev, 0);
-       if ((pdev->resource[0].flags & IORESOURCE_IO) != 0) {
+       if ((pci_resource_flags(pdev, 0) & IORESOURCE_IO) != 0) {
                printk(KERN_ERR "happymeal(PCI): Cannot find proper PCI device base address.\n");
                return -ENODEV;
        }
@@ -2887,22+2887,17 @@ static int __init happy_meal_sbus_probe(struct net_device *dev)
 #ifdef CONFIG_PCI
 static int __init happy_meal_pci_probe(struct net_device *dev)
 {
+       struct pci_dev *pdev = NULL;
        int cards = 0;
 
-       if (pci_present()) {
-               struct pci_dev *pdev;
-
-               pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-                                      PCI_DEVICE_ID_SUN_HAPPYMEAL, 0);
-               while (pdev != NULL) {
-                       if (cards)
-                               dev = NULL;
-                       cards++;
-                       happy_meal_pci_init(dev, pdev);
-                       pdev = pci_find_device(PCI_VENDOR_ID_SUN,
-                                              PCI_DEVICE_ID_SUN_HAPPYMEAL,
-                                              pdev);
-               }
+       while ((pdev = pci_find_device(PCI_VENDOR_ID_SUN,
+                                      PCI_DEVICE_ID_SUN_HAPPYMEAL, pdev)) != NULL) {
+               if (pci_enable_device(pdev))
+                       continue;
+               if (cards)
+                       dev = NULL;
+               cards++;
+               happy_meal_pci_init(dev, pdev);
        }
        return cards;
 }
index 39f87f7..2a4a7c2 100644 (file)
@@ -314,12+314,11 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        oi++;
                }
                if (csr5 & TimerInt) {
-#if 0
+
                        if (tulip_debug > 2)
                                printk(KERN_ERR "%s: Re-enabling interrupts, %8.8x.\n",
                                           dev->name, csr5);
                        outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
-#endif
                        tp->ttimer = 0;
                        oi++;
                }
@@ -327,14+326,19 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                        if (tulip_debug > 1)
                                printk(KERN_WARNING "%s: Too much work during an interrupt, "
                                           "csr5=0x%8.8x. (%lu) (%d,%d,%d)\n", dev->name, csr5, tp->nir, tx, rx, oi);
-                       /* Acknowledge all interrupt sources. */
-#if 0
-                       /* Clear all interrupting sources, set timer to re-enable. */
-                       outl(((~csr5) & 0x0001ebef) | NormalIntr | AbnormalIntr | TimerInt,
-                                ioaddr + CSR7);
-                       outl(12, ioaddr + CSR11);
-                       tp->ttimer = 1;
-#endif
+
+                       /* Acknowledge all interrupt sources. */
+                        outl(0x8001ffff, ioaddr + CSR5);
+                        if (tp->flags & HAS_INTR_MITIGATION) {
+                     /* Josip Loncaric at ICASE did extensive experimentation 
+                       to develop a good interrupt mitigation setting.*/
+                                outl(0x8b240000, ioaddr + CSR11);
+                        } else {
+                          /* Mask all interrupting sources, set timer to 
+                               re-enable. */
+                                outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7);
+                                outl(0x0012, ioaddr + CSR11);
+                        }
                        break;
                }
        } while (work_count-- > 0);
@@ -366,4+370,3 @@ void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
                           dev->name, inl(ioaddr + CSR5));
 
 }
-
index 4e2338b..c371ce0 100644 (file)
 #include <asm/unaligned.h>
 
 static char version[] __devinitdata =
-       "Linux Tulip driver version 0.9.9 (August 11, 2000)\n";
+       "Linux Tulip driver version 0.9.10 (September 6, 2000)\n";
 
 
 /* A few user-configurable values. */
@@ -167,6+167,8 @@ static struct pci_device_id tulip_pci_tbl[] __devinitdata = {
        { 0x1317, 0x1985, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x13D1, 0xAB02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x13D1, 0xAB03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+       { 0x104A, 0x0981, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
+       { 0x104A, 0x2774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
        { 0x11F6, 0x9881, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMPEX9881 },
        { 0x8086, 0x0039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, I21145 },
        { 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
index 547a180..cfe1a93 100644 (file)
@@ -303,7+303,7 @@ static int proc_read_clients(char *buf, char **start, off_t pos,
     
 ======================================================================*/
 
-static void setup_socket(socket_info_t *);
+static int setup_socket(socket_info_t *);
 static void shutdown_socket(socket_info_t *);
 static void reset_socket(socket_info_t *);
 static void unreset_socket(socket_info_t *);
@@ -490,9+490,12 @@ static void shutdown_socket(socket_info_t *s)
     free_regions(&s->c_region);
 } /* shutdown_socket */
 
-static void setup_socket(socket_info_t *s)
+/*
+ * Return zero if we think the card isn't actually present
+ */
+static int setup_socket(socket_info_t *s)
 {
-       int val;
+       int val, ret;
        int setup_timeout = 100;
 
        /* Wait for "not pending" */
@@ -506,7+509,8 @@ static void setup_socket(socket_info_t *s)
                }
                printk(KERN_NOTICE "cs: socket %p voltage interrogation"
                        " timed out\n", s);
-               return;
+               ret = 0;
+               goto out;
        }
 
        if (val & SS_DETECT) {
@@ -531,8+535,13 @@ static void setup_socket(socket_info_t *s)
                set_socket(s, &s->socket);
                msleep(vcc_settle);
                reset_socket(s);
-       } else
+               ret = 1;
+       } else {
                DEBUG(0, "cs: setup_socket(%p): no card!\n", s);
+               ret = 0;
+       }
+out:
+       return ret;
 } /* setup_socket */
 
 /*======================================================================
@@ -569,7+578,7 @@ static void unreset_socket(socket_info_t *s)
                get_socket_status(s, &val);
                if (val & SS_READY)
                        break;
-               DEBUG(2, "cs: socket %ld not ready yet\n", i);
+               DEBUG(2, "cs: socket %d not ready yet\n", s->sock);
                if (--setup_timeout) {
                        msleep(unreset_check);
                        continue;
@@ -673,7+682,8 @@ static void parse_events(void *info, u_int events)
                msleep(resume_delay);
            else
                msleep(setup_delay);
-           setup_socket(s);
+           if (setup_socket(s) == 0)
+               s->state &= ~SOCKET_SETUP_PENDING;
        }
     }
     if (events & SS_BATDEAD)
@@ -1415,7+1425,8 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
        if ((status & SS_DETECT) &&
            !(s->state & SOCKET_SETUP_PENDING)) {
            s->state |= SOCKET_SETUP_PENDING;
-           setup_socket(s);
+           if (setup_socket(s) == 0)
+                   s->state &= ~SOCKET_SETUP_PENDING;
        }
     }
 
@@ -2106,9+2117,7 @@ int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
        s->state |= SOCKET_SETUP_PENDING;
        spin_unlock_irqrestore(&s->lock, flags);
        get_socket_status(s, &status);
-       if (status & SS_DETECT)
-           setup_socket(s);
-       else {
+       if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) {
            s->state &= ~SOCKET_SETUP_PENDING;
            return CS_NO_CARD;
        }
index 45ee9dd..b3a53b4 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: dbri.c,v 1.19 2000/02/18 13:49:42 davem Exp $
+/* $Id: dbri.c,v 1.21 2000/08/31 23:44:17 davem Exp $
  * drivers/sbus/audio/dbri.c
  *
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -226,7+226,7 @@ static void dbri_detach(struct dbri *dbri)
         free_irq(dbri->irq, dbri);
         sbus_iounmap(dbri->regs, dbri->regs_size);
         sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma),
-                             dbri->dma, dbri->dma_dvma);
+                             (void *)dbri->dma, dbri->dma_dvma);
         kfree(dbri);
 }
 
@@ -2079,7+2079,9 @@ void dbri_liu_activate(int dev, int priority)
 void dbri_liu_deactivate(int dev)
 {
        struct dbri *dbri;
+#if 0
        u32 tmp;
+#endif
 
        if (dev >= num_drivers)
                return;
@@ -2228,7+2230,6 @@ static int dbri_attach(struct sparcaudio_driver *drv,
 {
        struct dbri *dbri;
        struct linux_prom_irqs irq;
-        __u32 dma_dvma;
        int err;
 
        if (sdev->prom_name[9] < 'e') {
@@ -2265,7+2266,7 @@ static int dbri_attach(struct sparcaudio_driver *drv,
        if (!dbri->regs) {
                printk(KERN_ERR "DBRI: could not allocate registers\n");
                 sbus_free_consistent(sdev, sizeof(struct dbri_dma),
-                                     dbri->dma, dbri->dma_dvma);
+                                     (void *)dbri->dma, dbri->dma_dvma);
                kfree(drv->private);
                return -EIO;
        }
@@ -2279,7+2280,7 @@ static int dbri_attach(struct sparcaudio_driver *drv,
                printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq);
                 sbus_iounmap(dbri->regs, dbri->regs_size);
                 sbus_free_consistent(sdev, sizeof(struct dbri_dma),
-                                     dbri->dma, dbri->dma_dvma);
+                                     (void *)dbri->dma, dbri->dma_dvma);
                kfree(drv->private);
                return err;
        }
index 84ee1ad..7c5a21b 100644 (file)
@@ -19,7+19,8 @@ ifeq ($(ARCH),sparc64)
 
 ifeq ($(CONFIG_PCI),y)
 
-O_OBJS += su.o pcikbd.o
+OX_OBJS += su.o
+O_OBJS += pcikbd.o
 
 ifeq ($(CONFIG_SAB82532),y)
 O_OBJS += sab82532.o
@@ -58,7+59,8 @@ endif
 else # !eq($(ARCH),sparc64)
 
 ifeq ($(CONFIG_PCI),y)
-O_OBJS += su.o pcikbd.o
+OX_OBJS += su.o
+O_OBJS += pcikbd.o
 endif
 
 endif # !eq($(ARCH),sparc64)
index 05a92c8..7d010f0 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: sab82532.c,v 1.47 2000/08/16 21:12:14 ecd Exp $
+/* $Id: sab82532.c,v 1.51 2000/09/04 19:41:26 ecd Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -55,9+55,11 @@ static int sab82532_refcount;
 /* Set of debugging defines */
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
+#undef SERIAL_DEBUG_MODEM
 #undef SERIAL_DEBUG_WAIT_UNTIL_SENT
 #undef SERIAL_DEBUG_SEND_BREAK
 #undef SERIAL_DEBUG_INTR
+#define SERIAL_DEBUG_OVERFLOW 1
 
 /* Trace things on serial device, useful for console debugging: */
 #undef SERIAL_LOG_DEVICE
@@ -79,10+81,15 @@ static struct tty_struct *sab82532_table[NR_PORTS];
 static struct termios *sab82532_termios[NR_PORTS];
 static struct termios *sab82532_termios_locked[NR_PORTS];
 
+#ifdef MODULE
+#undef CONFIG_SERIAL_CONSOLE
+#endif
+
 #ifdef CONFIG_SERIAL_CONSOLE
 extern int serial_console;
 static struct console sab82532_console;
 static int sab82532_console_init(void);
+static void batten_down_hatches(struct sab82532 *info);
 #endif
 
 #ifndef MIN
@@ -208,7+215,10 @@ static __inline__ void sab82532_start_tx(struct sab82532 *info)
        if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
                goto out;
 
+       info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+       writeb(info->interrupt_mask1, &info->regs->w.imr1);
        info->all_sent = 0;
+
        for (i = 0; i < info->xmit_fifo_size; i++) {
                u8 val = info->xmit_buf[info->xmit_tail++];
                writeb(val, &info->regs->w.xfifo[i]);
@@ -264,47+274,6 @@ static void sab82532_start(struct tty_struct *tty)
        restore_flags(flags);
 }
 
-static void batten_down_hatches(struct sab82532 *info)
-{
-       unsigned char saved_rfc, tmp;
-
-       if (!stop_a_enabled)
-               return;
-
-       /* If we are doing kadb, we call the debugger
-        * else we just drop into the boot monitor.
-        * Note that we must flush the user windows
-        * first before giving up control.
-        */
-       printk("\n");
-       flush_user_windows();
-
-       /*
-        * Set FIFO to single character mode.
-        */
-       saved_rfc = readb(&info->regs->r.rfc);
-       tmp = readb(&info->regs->rw.rfc);
-       tmp &= ~(SAB82532_RFC_RFDF);
-       writeb(tmp, &info->regs->rw.rfc);
-       sab82532_cec_wait(info);
-       writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
-
-#ifndef __sparc_v9__
-       if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
-           (((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))
-               sp_enter_debugger();
-       else
-#endif
-               prom_cmdline();
-
-       /*
-        * Reset FIFO to character + status mode.
-        */
-       writeb(saved_rfc, &info->regs->w.rfc);
-       sab82532_cec_wait(info);
-       writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
-}
-
 /*
  * ----------------------------------------------------------------------
  *
@@ -361,12+330,11 @@ static inline void receive_chars(struct sab82532 *info,
        if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
                sab82532_cec_wait(info);
                writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr);
-               /* Wait for command execution, to catch the TCD below. */
-               sab82532_cec_wait(info);
+               return;
        }
 
        if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
                printk("sab82532: receive_chars: RFO");
 #endif
                free_fifo++;
@@ -382,14+350,16 @@ static inline void receive_chars(struct sab82532 *info,
                writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
        }
 
+#ifdef CONFIG_SERIAL_CONSOLE
        if (info->is_console)
                wake_up(&keypress_wait);
+#endif
        if (!tty)
                return;
 
        for (i = 0; i < count; ) {
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
-#if 1
+#ifdef SERIAL_DEBUG_OVERFLOW
                        printk("sab82532: receive_chars: tty overrun\n");
 #endif
                        info->icount.buf_overrun++;
@@ -424,9+394,13 @@ static inline void transmit_chars(struct sab82532 *info,
 {
        int i;
 
-       if (stat->sreg.isr1 & SAB82532_ISR1_ALLS)
+       if (stat->sreg.isr1 & SAB82532_ISR1_ALLS) {
+               info->interrupt_mask1 |= SAB82532_IMR1_ALLS;
+               writeb(info->interrupt_mask1, &info->regs->w.imr1);
                info->all_sent = 1;
-       if (!(readb(&info->regs->r.star) & SAB82532_STAR_XFW))
+       }
+
+       if (!(stat->sreg.isr1 & SAB82532_ISR1_XPR))
                return;
 
        if (!info->tty) {
@@ -442,8+416,11 @@ static inline void transmit_chars(struct sab82532 *info,
                return;
        }
 
-       /* Stuff 32 bytes into Transmit FIFO. */
+       info->interrupt_mask1 &= ~(SAB82532_IMR1_ALLS);
+       writeb(info->interrupt_mask1, &info->regs->w.imr1);
        info->all_sent = 0;
+
+       /* Stuff 32 bytes into Transmit FIFO. */
        for (i = 0; i < info->xmit_fifo_size; i++) {
                u8 val = info->xmit_buf[info->xmit_tail++];
                writeb(val, &info->regs->w.xfifo[i]);
@@ -476,10+453,12 @@ static inline void check_status(struct sab82532 *info,
        int modem_change = 0;
 
        if (stat->sreg.isr1 & SAB82532_ISR1_BRK) {
+#ifdef CONFIG_SERIAL_CONSOLE
                if (info->is_console) {
                        batten_down_hatches(info);
                        return;
                }
+#endif
                if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
                        info->icount.buf_overrun++;
                        goto check_modem;
@@ -509,7+488,7 @@ check_modem:
                info->dcd = (readb(&info->regs->r.vstr) & SAB82532_VSTR_CD) ? 0 : 1;
                info->icount.dcd++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("DCD change: %d\n", info->icount.dcd);
 #endif
        }
@@ -517,7+496,7 @@ check_modem:
                info->cts = readb(&info->regs->r.star) & SAB82532_STAR_CTS;
                info->icount.cts++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("CTS change: %d, CTS %s\n", info->icount.cts, info->cts ? "on" : "off");
 #endif
        }
@@ -525,7+504,7 @@ check_modem:
                info->dsr = (readb(&info->regs->r.pvr) & info->pvr_dsr_bit) ? 0 : 1;
                info->icount.dsr++;
                modem_change++;
-#if 0
+#ifdef SERIAL_DEBUG_MODEM
                printk("DSR change: %d\n", info->icount.dsr);
 #endif
        }
@@ -828,10+807,12 @@ static int startup(struct sab82532 *info)
        info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
                                SAB82532_IMR0_PLLA;
        writeb(info->interrupt_mask0, &info->regs->w.imr0);
-       info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_XOFF |
-                               SAB82532_IMR1_TIN | SAB82532_IMR1_CSC |
-                               SAB82532_IMR1_XON | SAB82532_IMR1_XPR;
+       info->interrupt_mask1 = SAB82532_IMR1_BRKT | SAB82532_IMR1_ALLS |
+                               SAB82532_IMR1_XOFF | SAB82532_IMR1_TIN |
+                               SAB82532_IMR1_CSC | SAB82532_IMR1_XON |
+                               SAB82532_IMR1_XPR;
        writeb(info->interrupt_mask1, &info->regs->w.imr1);
+       info->all_sent = 1;
 
        if (info->tty)
                clear_bit(TTY_IO_ERROR, &info->tty->flags);
@@ -880,6+861,7 @@ static void shutdown(struct sab82532 *info)
                info->xmit_buf = 0;
        }
 
+#ifdef CONFIG_SERIAL_CONSOLE
        if (info->is_console) {
                info->interrupt_mask0 = SAB82532_IMR0_PERR | SAB82532_IMR0_FERR |
                                        SAB82532_IMR0_PLLA | SAB82532_IMR0_CDSC;
@@ -895,6+877,7 @@ static void shutdown(struct sab82532 *info)
                restore_flags(flags);
                return;
        }
+#endif
 
        /* Disable Interrupts */
        info->interrupt_mask0 = 0xff;
@@ -1238,10+1221,6 @@ static void sab82532_throttle(struct tty_struct * tty)
        
        if (I_IXOFF(tty))
                sab82532_send_xchar(tty, STOP_CHAR(tty));
-#if 0
-       if (tty->termios->c_cflag & CRTSCTS)
-               writeb(readb(&info->regs->rw.mode) | SAB82532_MODE_RTS, &info->regs->rw.mode);
-#endif
 }
 
 static void sab82532_unthrottle(struct tty_struct * tty)
@@ -1263,11+1242,6 @@ static void sab82532_unthrottle(struct tty_struct * tty)
                else
                        sab82532_send_xchar(tty, START_CHAR(tty));
        }
-
-#if 0
-       if (tty->termios->c_cflag & CRTSCTS)
-               writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RTS), &info->regs->rw.mode);
-#endif
 }
 
 /*
@@ -1562,18+1536,6 @@ static void sab82532_set_termios(struct tty_struct *tty,
                tty->hw_stopped = 0;
                sab82532_start(tty);
        }
-
-#if 0
-       /*
-        * No need to wake up processes in open wait, since they
-        * sample the CLOCAL flag once, and don't recheck it.
-        * XXX  It's not clear whether the current behavior is correct
-        * or not.  Hence, this may change.....
-        */
-       if (!(old_termios->c_cflag & CLOCAL) &&
-           (tty->termios->c_cflag & CLOCAL))
-               wake_up_interruptible(&info->open_wait);
-#endif
 }
 
 /*
@@ -1651,9+1613,6 @@ static void sab82532_close(struct tty_struct *tty, struct file * filp)
         */
        info->interrupt_mask0 |= SAB82532_IMR0_TCD;
        writeb(info->interrupt_mask0, &info->regs->w.imr0);
-#if 0
-       writeb(readb(&info->regs->rw.mode) & ~(SAB82532_MODE_RAC), &info->regs->rw.mode);
-#endif
        if (info->flags & ASYNC_INITIALIZED) {
                /*
                 * Before we drop DTR, make sure the UART transmitter
@@ -1722,7+1681,6 @@ static void sab82532_wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
-       current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_WAIT_UNTIL_SENT
        printk("xmit_cnt = %d, alls = %d (jiff=%lu)...done\n", info->xmit_cnt, info->all_sent, jiffies);
 #endif
@@ -1738,8+1696,10 @@ static void sab82532_hangup(struct tty_struct *tty)
        if (serial_paranoia_check(info, tty->device, "sab82532_hangup"))
                return;
 
+#ifdef CONFIG_SERIAL_CONSOLE
        if (info->is_console)
                return;
+#endif
 
        sab82532_flush_buffer(tty);
        shutdown(info);
@@ -1873,7+1833,6 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
                schedule();
        }
-       current->state = TASK_RUNNING;
        remove_wait_queue(&info->open_wait, &wait);
        if (!tty_hung_up_p(filp))
                info->count++;
@@ -2010,7+1969,7 @@ line_info(char *buf, struct sab82532 *info)
        char stat_buf[30];
        int ret;
 
-       ret = sprintf(buf, "%d: uart:SAB82532 ", info->line);
+       ret = sprintf(buf, "%u: uart:SAB82532 ", info->line);
        switch (info->type) {
                case 0:
                        ret += sprintf(buf+ret, "V1.0 ");
@@ -2056,19+2015,22 @@ line_info(char *buf, struct sab82532 *info)
        restore_flags(flags);
 
        if (info->baud)
-               ret += sprintf(buf+ret, " baud:%d", info->baud);
+               ret += sprintf(buf+ret, " baud:%u", info->baud);
+
+       ret += sprintf(buf+ret, " tx:%u rx:%u",
+                      info->icount.tx, info->icount.rx);
 
        if (info->icount.frame)
-               ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+               ret += sprintf(buf+ret, " fe:%u", info->icount.frame);
 
        if (info->icount.parity)
-               ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+               ret += sprintf(buf+ret, " pe:%u", info->icount.parity);
 
        if (info->icount.brk)
-               ret += sprintf(buf+ret, " brk:%d", info->icount.brk);
+               ret += sprintf(buf+ret, " brk:%u", info->icount.brk);
 
        if (info->icount.overrun)
-               ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+               ret += sprintf(buf+ret, " oe:%u", info->icount.overrun);
 
        /*
         * Last thing is the RS-232 status lines.
@@ -2161,15+2123,17 @@ ebus_done:
        return 0;
 }
 
+#ifndef MODULE
 static void __init sab82532_kgdb_hook(int line)
 {
        prom_printf("sab82532: kgdb support is not implemented, yet\n");
        prom_halt();
 }
+#endif
 
 static inline void __init show_serial_version(void)
 {
-       char *revision = "$Revision: 1.47 $";
+       char *revision = "$Revision: 1.51 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
@@ -2246,7+2210,11 @@ int __init sab82532_init(void)
         * major number and the subtype code.
         */
        callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
        callout_driver.name = "cua/%d";
+#else
+       callout_driver.name = "cua";
+#endif
        callout_driver.major = TTYAUX_MAJOR;
        callout_driver.subtype = SERIAL_TYPE_CALLOUT;
        callout_driver.read_proc = 0;
@@ -2364,8+2332,10 @@ found:
 #ifdef CONFIG_SERIAL_CONSOLE
        sunserial_setinitfunc(sab82532_console_init);
 #endif
+#ifndef MODULE
        sunserial_setinitfunc(sab82532_init);
        rs_ops.rs_kgdb_hook = sab82532_kgdb_hook;
+#endif
        return 0;
 }
 
@@ -2400,12+2370,56 @@ void cleanup_module(void)
                free_page((unsigned long) tmp_buf);
                tmp_buf = NULL;
        }
-       for (sab = sab82532_chain; sab; sab = sab->next)
+       for (sab = sab82532_chain; sab; sab = sab->next) {
+               if (!(sab->line & 0x01))
+                       free_irq(sab->irq, sab);
                iounmap(sab->regs);
+       }
 }
 #endif /* MODULE */
 
 #ifdef CONFIG_SERIAL_CONSOLE
+static void
+batten_down_hatches(struct sab82532 *info)
+{
+       unsigned char saved_rfc, tmp;
+
+       if (!stop_a_enabled)
+               return;
+
+       /* If we are doing kadb, we call the debugger
+        * else we just drop into the boot monitor.
+        * Note that we must flush the user windows
+        * first before giving up control.
+        */
+       printk("\n");
+       flush_user_windows();
+
+       /*
+        * Set FIFO to single character mode.
+        */
+       saved_rfc = readb(&info->regs->r.rfc);
+       tmp = readb(&info->regs->rw.rfc);
+       tmp &= ~(SAB82532_RFC_RFDF);
+       writeb(tmp, &info->regs->rw.rfc);
+       sab82532_cec_wait(info);
+       writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
+
+#ifndef __sparc_v9__
+       if ((((unsigned long)linux_dbvec) >= DEBUG_FIRSTVADDR) &&
+           (((unsigned long)linux_dbvec) <= DEBUG_LASTVADDR))
+               sp_enter_debugger();
+       else
+#endif
+               prom_cmdline();
+
+       /*
+        * Reset FIFO to character + status mode.
+        */
+       writeb(saved_rfc, &info->regs->w.rfc);
+       sab82532_cec_wait(info);
+       writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
+}
 
 static __inline__ void
 sab82532_console_putchar(struct sab82532 *info, char c)
@@ -2645,4+2659,3 @@ dprintf(const char *fmt, ...)
 }
 #endif /* SERIAL_LOG_DEVICE */
 #endif /* CONFIG_SERIAL_CONSOLE */
-
index 6df7d99..c6e9032 100644 (file)
@@ -1,4+1,4 @@
-/* $Id: su.c,v 1.38 2000/04/22 00:45:16 davem Exp $
+/* $Id: su.c,v 1.41 2000/09/04 19:41:27 ecd Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -1851,7+1851,6 @@ su_wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
-       current->state = TASK_RUNNING;
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
@@ -2002,7+2001,6 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 #endif
                schedule();
        }
-       current->state = TASK_RUNNING;
        remove_wait_queue(&info->open_wait, &wait);
        if (extra_count)
                info->count++;
@@ -2125,14+2123,12 @@ line_info(char *buf, struct su_struct *info)
        int             ret;
        unsigned long   flags;
 
-       ret = sprintf(buf, "%d: uart:%s port:%X irq:%s",
-                     info->line, uart_config[info->type].name, 
-                     (int)info->port, __irq_itoa(info->irq));
+       if (info->port == 0 || info->type == PORT_UNKNOWN)
+               return 0;
 
-       if (info->port == 0 || info->type == PORT_UNKNOWN) {
-               ret += sprintf(buf+ret, "\n");
-               return ret;
-       }
+       ret = sprintf(buf, "%u: uart:%s port:%lX irq:%s",
+                     info->line, uart_config[info->type].name, 
+                     (unsigned long)info->port, __irq_itoa(info->irq));
 
        /*
         * Figure out the current RS-232 lines
@@ -2158,24+2154,24 @@ line_info(char *buf, struct su_struct *info)
                strcat(stat_buf, "|RI");
 
        if (info->quot) {
-               ret += sprintf(buf+ret, " baud:%d",
+               ret += sprintf(buf+ret, " baud:%u",
                               info->baud_base / info->quot);
        }
 
-       ret += sprintf(buf+ret, " tx:%d rx:%d",
-                     info->icount.tx, info->icount.rx);
+       ret += sprintf(buf+ret, " tx:%u rx:%u",
+                      info->icount.tx, info->icount.rx);
 
        if (info->icount.frame)
-               ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+               ret += sprintf(buf+ret, " fe:%u", info->icount.frame);
 
        if (info->icount.parity)
-               ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+               ret += sprintf(buf+ret, " pe:%u", info->icount.parity);
 
        if (info->icount.brk)
-               ret += sprintf(buf+ret, " brk:%d", info->icount.brk);   
+               ret += sprintf(buf+ret, " brk:%u", info->icount.brk);   
 
        if (info->icount.overrun)
-               ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+               ret += sprintf(buf+ret, " oe:%u", info->icount.overrun);
 
        /*
         * Last thing is the RS-232 status lines
@@ -2223,7+2219,7 @@ done:
  */
 static __inline__ void __init show_su_version(void)
 {
-       char *revision = "$Revision: 1.38 $";
+       char *revision = "$Revision: 1.41 $";
        char *version, *p;
 
        version = strchr(revision, ' ');
@@ -2425,6+2421,7 @@ ebus_done:
  * numbers start, we always are probed for first.
  */
 int su_num_ports = 0;
+EXPORT_SYMBOL(su_num_ports);
 
 /*
  * The serial driver boot-time initialization code!
@@ -2442,7+2439,11 @@ int __init su_serial_init(void)
        memset(&serial_driver, 0, sizeof(struct tty_driver));
        serial_driver.magic = TTY_DRIVER_MAGIC;
        serial_driver.driver_name = "su";
-       serial_driver.name = "ttys/%d";
+#ifdef CONFIG_DEVFS_FS
+       serial_driver.name = "tts/%d";
+#else
+       serial_driver.name = "ttyS";
+#endif
        serial_driver.major = TTY_MAJOR;
        serial_driver.minor_start = 64;
        serial_driver.num = NR_PORTS;
@@ -2482,7+2483,11 @@ int __init su_serial_init(void)
         * major number and the subtype code.
         */
        callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
        callout_driver.name = "cua/%d";
+#else
+       callout_driver.name = "cua";
+#endif
        callout_driver.major = TTYAUX_MAJOR;
        callout_driver.subtype = SERIAL_TYPE_CALLOUT;
        callout_driver.read_proc = 0;
@@ -2598,6+2603,17 @@ void __init su_probe_any(struct su_probe_scan *t, int sunode)
                                t->msx = t->devices;
                                info->port_type = SU_PORT_MS;
                        } else {
+#ifdef __sparc_v9__
+                               /*
+                                * Do not attempt to use the truncated
+                                * keyboard/mouse ports as serial ports
+                                * on Ultras with PC keyboard attached.
+                                */
+                               if (prom_getbool(sunode, "mouse"))
+                                       continue;
+                               if (prom_getbool(sunode, "keyboard"))
+                                       continue;
+#endif
                                info->port_type = SU_PORT_PORT;
                        }
                        info->is_console = 0;
index 554a156..77b849e 100644 (file)
 #include "vfc.h"
 #include <asm/vfc_ioctls.h>
 
+static struct file_operations vfc_fops;
 static devfs_handle_t devfs_handle = NULL;  /*  For the directory  */
 struct vfc_dev **vfc_dev_lst;
 static char vfcstr[]="vfc";
index 2950667..0efe86c 100644 (file)
  *       scsi disks using eight major numbers.
  *
  *       Modified by Richard Gooch rgooch@atnf.csiro.au to support devfs.
+ *     
+ *      Modified by Torben Mathiasen tmm@image.dk
+ *       Resource allocation fixes in sd_init and cleanups.
  */
 
 #include <linux/config.h>
@@ -1039,16+1042,24 @@ static int sd_init()
        if (rscsi_disks)
                return 0;
 
-       rscsi_disks = (Scsi_Disk *)
-           kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
+       rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
+       if (!rscsi_disks)
+               goto cleanup_devfs;
        memset(rscsi_disks, 0, sd_template.dev_max * sizeof(Scsi_Disk));
 
        /* for every (necessary) major: */
-       sd_sizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+       sd_sizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+       if (!sd_sizes)
+               goto cleanup_disks;
        memset(sd_sizes, 0, (sd_template.dev_max << 4) * sizeof(int));
 
-       sd_blocksizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
-       sd_hardsizes = (int *) kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+       sd_blocksizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+       if (!sd_blocksizes)
+               goto cleanup_sizes;
+       
+       sd_hardsizes = kmalloc((sd_template.dev_max << 4) * sizeof(int), GFP_ATOMIC);
+       if (!sd_hardsizes)
+               goto cleanup_blocksizes;
 
        for (i = 0; i < sd_template.dev_max << 4; i++) {
                sd_blocksizes[i] = 1024;
@@ -1059,22+1070,29 @@ static int sd_init()
                blksize_size[SD_MAJOR(i)] = sd_blocksizes + i * (SCSI_DISKS_PER_MAJOR << 4);
                hardsect_size[SD_MAJOR(i)] = sd_hardsizes + i * (SCSI_DISKS_PER_MAJOR << 4);
        }
-       sd = (struct hd_struct *) kmalloc((sd_template.dev_max << 4) *
+       sd = kmalloc((sd_template.dev_max << 4) *
                                          sizeof(struct hd_struct),
                                          GFP_ATOMIC);
+       if (!sd)
+               goto cleanup_sd;
        memset(sd, 0, (sd_template.dev_max << 4) * sizeof(struct hd_struct));
 
        if (N_USED_SD_MAJORS > 1)
-               sd_gendisks = (struct gendisk *)
-                   kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+               sd_gendisks = kmalloc(N_USED_SD_MAJORS * sizeof(struct gendisk), GFP_ATOMIC);
+               if (!sd_gendisks)
+                       goto cleanup_sd_gendisks;
        for (i = 0; i < N_USED_SD_MAJORS; i++) {
                sd_gendisks[i] = sd_gendisk;
                sd_gendisks[i].de_arr = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr,
                                                  GFP_ATOMIC);
+               if (!sd_gendisks[i].de_arr)
+                       goto cleanup_gendisks_de_arr;
                 memset (sd_gendisks[i].de_arr, 0,
                         SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].de_arr);
                sd_gendisks[i].flags = kmalloc (SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags,
                                                 GFP_ATOMIC);
+               if (!sd_gendisks[i].flags)
+                       goto cleanup_gendisks_flags;
                 memset (sd_gendisks[i].flags, 0,
                         SCSI_DISKS_PER_MAJOR * sizeof *sd_gendisks[i].flags);
                sd_gendisks[i].major = SD_MAJOR(i);
@@ -1091,6+1109,31 @@ static int sd_init()
 
        LAST_SD_GENDISK.next = NULL;
        return 0;
+
+cleanup_gendisks_flags:
+       kfree(sd_gendisks[i].de_arr);
+cleanup_gendisks_de_arr:
+       while (--i >= 0 ) {
+               kfree(sd_gendisks[i].de_arr);
+               kfree(sd_gendisks[i].flags);
+       }
+       kfree(sd_gendisks);
+cleanup_sd_gendisks:
+       kfree(sd);
+cleanup_sd:
+       kfree(sd_hardsizes);
+cleanup_blocksizes:
+       kfree(sd_blocksizes);
+cleanup_sizes:
+       kfree(sd_sizes);
+cleanup_disks:
+       kfree(rscsi_disks);
+cleanup_devfs:
+       for (i = 0; i < N_USED_SD_MAJORS; i++) {
+               devfs_unregister_blkdev(SD_MAJOR(i), "sd");
+       }
+       sd_registered--;
+       return 1;
 }
 
 
@@ -1292,14+1335,12 @@ static void sd_detach(Scsi_Device * SDp)
        return;
 }
 
-#ifdef MODULE
-
-int init_module(void)
+int init_sd(void)
 {
-       sd_template.module = &__this_module;
+       sd_template.module = THIS_MODULE;
        return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
 }
-void cleanup_module(void)
+void exit_sd(void)
 {
        struct gendisk **prev_sdgd_link;
        struct gendisk *sdgd;
@@ -1313,10+1354,10 @@ void cleanup_module(void)
 
        sd_registered--;
        if (rscsi_disks != NULL) {
-               kfree((char *) rscsi_disks);
-               kfree((char *) sd_sizes);
-               kfree((char *) sd_blocksizes);
-               kfree((char *) sd_hardsizes);
+               kfree(rscsi_disks);
+               kfree(sd_sizes);
+               kfree(sd_blocksizes);
+               kfree(sd_hardsizes);
                kfree((char *) sd);
 
                /*
@@ -1346,23+1387,6 @@ void cleanup_module(void)
        if (sd_gendisks != &sd_gendisk)
                kfree(sd_gendisks);
 }
-#endif                         /* MODULE */
 
-/*
- * Overrides for Emacs so that we almost follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
+module_init(init_sd);
+module_exit(exit_sd);
index b18a96b..da89d29 100644 (file)
 #include <linux/errno.h>
 #include <linux/cdrom.h>
 #include <linux/interrupt.h>
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
index fd23967..0100595 100644 (file)
@@ -6,6+6,9 @@
  *
  * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B
  *
+ * (08/06/2000) Version 0.5 gkh
+ *     Fixed problem of not resubmitting the bulk read urb if there is
+ *     an error in the callback.  Ericsson devices seem to need this.
  *
  * (07/11/2000) Version 0.4 gkh
  *     Fixed bug in disconnect for when we call tty_hangup
@@ -796,17+799,17 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
 
        if (!bluetooth) {
                dbg(__FUNCTION__ " - bad bluetooth pointer, exiting");
-               return;
+               goto exit;
        }
 
        if (urb->status) {
                dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status);
-               return;
+               goto exit;
        }
 
        if (!count) {
                dbg(__FUNCTION__ " - zero length read bulk");
-               return;
+               goto exit;
        }
 
 #ifdef DEBUG
@@ -832,9+835,7 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
        if (bluetooth->bulk_packet_pos + count > ACL_BUFFER_SIZE) {
                err(__FUNCTION__ " - exceeded ACL_BUFFER_SIZE");
                bluetooth->bulk_packet_pos = 0;
-               if (usb_submit_urb(urb))
-                       dbg(__FUNCTION__ " - failed resubmitting read urb");
-               return;
+               goto exit;
        }
 
        memcpy (&bluetooth->bulk_buffer[bluetooth->bulk_packet_pos],
@@ -845,17+846,13 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
        if (bluetooth->bulk_packet_pos >= ACL_HDR_SIZE) {
                packet_size = CHAR2INT16(bluetooth->bulk_buffer[4],bluetooth->bulk_buffer[3]);
        } else {
-               if (usb_submit_urb(urb))
-                       dbg(__FUNCTION__ " - failed resubmitting read urb");
-               return;
+               goto exit;
        }
 
        if (packet_size + ACL_HDR_SIZE < bluetooth->bulk_packet_pos) {
                err(__FUNCTION__ " - packet was too long");
                bluetooth->bulk_packet_pos = 0;
-               if (usb_submit_urb(urb))
-                       dbg(__FUNCTION__ " - failed resubmitting read urb");
-               return;
+               goto exit;
        }
 
        if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) {
@@ -865,6+862,7 @@ static void bluetooth_read_bulk_callback (struct urb *urb)
                bluetooth->bulk_packet_pos = 0;
        }       
 
+exit:
        if (usb_submit_urb(urb))
                dbg(__FUNCTION__ " - failed resubmitting read urb");
 
index a998228..d14e8e9 100644 (file)
@@ -837,7+837,6 @@ static void __exit dabusb_cleanup (void)
 
 /* --------------------------------------------------------------------- */
 
-#ifdef MODULE
 MODULE_AUTHOR ("Deti Fliegl, deti@fliegl.de");
 MODULE_DESCRIPTION ("DAB-USB Interface Driver for Linux (c)1999");
 MODULE_PARM (buffers, "i");
@@ -846,7+845,4 @@ MODULE_PARM_DESC (buffers, "Number of buffers (default=256)");
 module_init (dabusb_init);
 module_exit (dabusb_cleanup);
 
-
-#endif
-
 /* --------------------------------------------------------------------- */
index ca1d8ab..aa6372b 100644 (file)
 
  History:
 
+ Version 0.24:
+       Markus: Hope I got these silly VIDEO_TUNER_LOW issues finally
+       right.  Some minor cleanup, improved standalone compilation
+
  Version 0.23:
        Markus: Sign extension bug fixed by declaring transfer_buffer unsigned
 
@@ -135,11+139,11 @@ static int dsbr100_stop(usb_dsbr100 *radio)
 
 static int dsbr100_setfreq(usb_dsbr100 *radio, int freq)
 {
-       freq = (freq*80)/16+856;
+       freq = (freq/16*80)/1000+856;
        if (usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
-               0x01, 0xC0, (freq&0xff00)>>8, freq&0xff, 
-               radio->transfer_buffer, 8, 300)<0
-        || usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
+               0x01, 0xC0, (freq>>8)&0x00ff, freq&0xff, 
+               radio->transfer_buffer, 8, 300)<0 ||
+           usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
                0x00, 0xC0, 0x96, 0xB7, radio->transfer_buffer, 8, 300)<0 ||
            usb_control_msg(radio->dev, usb_rcvctrlpipe(radio->dev, 0),
                0x00, 0xC0, 0x00, 0x24, radio->transfer_buffer, 8, 300)<0) {
@@ -172,7+176,7 @@ static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum)
        usb_dsbr100_radio.priv = radio;
        radio->dev = dev;
        radio->ifnum = ifnum;
-       radio->curfreq = 1454;
+       radio->curfreq = 1454000;
        return (void*)radio;
 }
 
@@ -218,8+222,8 @@ static int usb_dsbr100_ioctl(struct video_device *dev, unsigned int cmd,
                                return -EFAULT;
                        if(v.tuner)     /* Only 1 tuner */ 
                                return -EINVAL;
-                       v.rangelow = 87*16;
-                       v.rangehigh = 108*16;
+                       v.rangelow = 87*16000;
+                       v.rangehigh = 108*16000;
                        v.flags = VIDEO_TUNER_LOW;
                        v.mode = VIDEO_MODE_AUTO;
                        v.signal = radio->stereo*0x7000;
index b550733..a242db7 100644 (file)
@@ -48,6+48,7 @@ static LIST_HEAD(superlist);
 struct special {
        const char *name;
        struct file_operations *fops;
+       struct inode *inode;
        struct list_head inodes;
 };
 
@@ -572,6+573,7 @@ struct super_block *usbdevfs_read_super(struct super_block *s, void *data, int s
                inode->i_uid = listuid;
                inode->i_gid = listgid;
                inode->i_mode = listmode | S_IFREG;
+               special[i].inode = inode;
                list_add_tail(&inode->u.usbdev_i.slist, &s->u.usbdevfs_sb.ilist);
                list_add_tail(&inode->u.usbdev_i.dlist, &special[i].inodes);
        }
@@ -598,6+600,17 @@ static DECLARE_FSTYPE(usbdevice_fs_type, "usbdevfs", usbdevfs_read_super, 0);
 
 /* --------------------------------------------------------------------- */
 
+static void update_special_inodes (void)
+{
+       int i;
+       for (i = 0; i < NRSPECIAL; i++) {
+               struct inode *inode = special[i].inode;
+               if (inode)
+                       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       }
+}
+
+
 void usbdevfs_add_bus(struct usb_bus *bus)
 {
        struct list_head *slist;
@@ -605,6+618,7 @@ void usbdevfs_add_bus(struct usb_bus *bus)
        lock_kernel();
        for (slist = superlist.next; slist != &superlist; slist = slist->next)
                new_bus_inode(bus, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+       update_special_inodes();
        unlock_kernel();
        usbdevfs_conn_disc_event();
 }
@@ -614,6+628,7 @@ void usbdevfs_remove_bus(struct usb_bus *bus)
        lock_kernel();
        while (!list_empty(&bus->inodes))
                free_inode(list_entry(bus->inodes.next, struct inode, u.usbdev_i.dlist));
+       update_special_inodes();
        unlock_kernel();
        usbdevfs_conn_disc_event();
 }
@@ -625,6+640,7 @@ void usbdevfs_add_device(struct usb_device *dev)
        lock_kernel();
        for (slist = superlist.next; slist != &superlist; slist = slist->next)
                new_dev_inode(dev, list_entry(slist, struct super_block, u.usbdevfs_sb.slist));
+       update_special_inodes();
        unlock_kernel();
        usbdevfs_conn_disc_event();
 }
@@ -652,6+668,8 @@ void usbdevfs_remove_device(struct usb_device *dev)
                        send_sig_info(ds->discsignr, &sinfo, ds->disctask);
                }
        }
+
+       update_special_inodes();
        unlock_kernel();
        usbdevfs_conn_disc_event();
 }
index b8eb74c..fdfe5f3 100644 (file)
  *     20000603 Version 0.2.1
  *     20000620 minor cosmetic changes
  *     20000620 Version 0.2.2
+ *  20000822 Hopefully fixed deadlock in mts_remove_nolock()
+ *  20000822 Fixed minor race in mts_transfer_cleanup()
+ *  20000822 Fixed deadlock on submission error in queuecommand
+ *  20000822 Version 0.2.3
  */
 
 #include <linux/module.h>
 
 /* Should we do debugging? */
 
-#define MTS_DO_DEBUG
+// #define MTS_DO_DEBUG
 
 
 /* USB layer driver interface */
@@ -147,7+151,7 @@ static struct usb_driver mts_usb_driver = {
 
 /* Internal driver stuff */
 
-#define MTS_VERSION    "0.2.2"
+#define MTS_VERSION    "0.2.3"
 #define MTS_NAME       "microtek usb (rev " MTS_VERSION "): "
 
 #define MTS_WARNING(x...) \
@@ -332,9+336,8 @@ void mts_remove_nolock( struct mts_desc* to_remove )
        MTS_DEBUG( "removing 0x%x from list\n",
                   (int)to_remove );
 
+       lock_kernel();
        mts_wait_abort(to_remove);
-       
-       down( &to_remove->lock );
 
        MTS_DEBUG_GOT_HERE();
        
@@ -358,6+361,7 @@ void mts_remove_nolock( struct mts_desc* to_remove )
 
        MTS_DEBUG_GOT_HERE();
        scsi_unregister_module(MODULE_SCSI_HA, &(to_remove->ctempl));
+       unlock_kernel();
        
        kfree( to_remove );
 }
@@ -391,7+395,7 @@ static int mts_scsi_release(struct Scsi_Host *psh)
 }
 
 static int mts_scsi_abort (Scsi_Cmnd *srb)
-/* interrupt context (!) */
+/* interrupt context (!) */ /* FIXME this is about to become task context */
 {
        struct mts_desc* desc = (struct mts_desc*)(srb->host->hostdata[0]);
 
@@ -508,9+512,9 @@ static void mts_transfer_cleanup( struct urb *transfer )
 {
        struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context;
        
-       up( &context->instance->lock );
        if ( context->final_callback )
                context->final_callback(context->srb);
+       up( &context->instance->lock );
 
 }
 
@@ -708,6+712,7 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
 
                if(callback)
                        callback(srb);
+       up(&desc->lock); /* no further cleanup is done */
 
                goto out;
        }       
index b8b5993..0fba2ff 100644 (file)
@@ -130,9+130,9 @@ static inline void set_break        (struct usb_serial_port *port, unsigned char brk);
  *****************************************************************************/
 static void command_port_write_callback (struct urb *urb)
 {
-       unsigned char *data = urb->transfer_buffer;
 #ifdef DEBUG
        int i;
+       unsigned char *data = urb->transfer_buffer;
 #endif
 
        dbg (__FUNCTION__);
index 8423b44..db13c25 100644 (file)
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
@@ -2425,7+2426,7 @@ static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data)
        return 0;
 }
 
-int uhci_init(void)
+static int __init uhci_init(void)
 {
        int retval;
        struct pci_dev *dev;
@@ -2531,19+2532,15 @@ void uhci_cleanup(void)
                printk(KERN_INFO "uhci: not all TD's were freed\n");
 }
 
-#ifdef MODULE
-int init_module(void)
-{
-       return uhci_init();
-}
-
-void cleanup_module(void)
+static void __exit uhci_exit(void)
 {
        pm_unregister_all(handle_pm_event);
        uhci_cleanup();
 }
 
+module_init(uhci_init);
+module_exit(uhci_exit);
+
 MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
 MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
-#endif //MODULE
 
index 7f124b8..a187560 100644 (file)
@@ -54,17+54,6 @@ static int __init usb_init(void)
        usbdevfs_init();
        usb_hub_init();
 
-#ifndef CONFIG_USB_MODULE
-#ifdef CONFIG_USB_UHCI
-       uhci_init();
-#endif
-#ifdef CONFIG_USB_UHCI_ALT
-       uhci_init();
-#endif
-#ifdef CONFIG_USB_OHCI
-       ohci_hcd_init(); 
-#endif
-#endif
        return 0;
 }
 
index 316394a..ab042c4 100644 (file)
@@ -2375,7+2375,7 @@ static struct pmu_sleep_notifier ohci_sleep_notifier = {
 
 /*-------------------------------------------------------------------------*/
 
-int __init ohci_hcd_init (void) 
+static int __init ohci_hcd_init (void) 
 {
        int ret = pci_module_init (&ohci_pci_driver);
 
@@ -2386,11+2386,10 @@ int __init ohci_hcd_init (void)
        return ret;
 }
 
-#ifdef MODULE
 
 /*-------------------------------------------------------------------------*/
 
-void __exit ohci_hcd_cleanup (void) 
+static void __exit ohci_hcd_cleanup (void) 
 {      
 #ifdef CONFIG_PMAC_PBOOK
        pmu_unregister_sleep_notifier (&ohci_sleep_notifier);
@@ -2401,7+2400,6 @@ void __exit ohci_hcd_cleanup (void)
 module_init (ohci_hcd_init);
 module_exit (ohci_hcd_cleanup);
 
-#endif /* MODULE */
 
 
 MODULE_AUTHOR ("Roman Weissgaerber <weissg@vienna.at>");
index 14c6e64..709fc02 100644 (file)
@@ -2822,7+2822,7 @@ _static int __init start_uhci (struct pci_dev *dev)
        return -1;
 }
 
-int __init uhci_init (void)
+static int __init uhci_init (void)
 {
        int retval = -ENODEV;
        struct pci_dev *dev = NULL;
@@ -2879,7+2879,7 @@ int __init uhci_init (void)
        return retval;
 }
 
-void __exit uhci_cleanup (void)
+static void __exit uhci_cleanup (void)
 {
        uhci_t *s;
        while ((s = devs)) {
@@ -2895,18+2895,15 @@ void __exit uhci_cleanup (void)
 #endif
 }
 
-#ifdef MODULE
-int init_module (void)
-{
-       return uhci_init ();
-}
-
-void cleanup_module (void)
+static void __exit uhci_exit (void)
 {
        pm_unregister_all (handle_pm_event);
        uhci_cleanup ();
 }
 
+module_init(uhci_init);
+module_exit(uhci_exit);
+
 MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber");
 MODULE_DESCRIPTION("USB Universal Host Controller Interface driver");
-#endif //MODULE
+
index 12cb880..da61b52 100644 (file)
@@ -484,16+484,12 @@ static size_t parport_uss720_write_compat(struct parport *pp, const void *buffer
 
 void parport_uss720_inc_use_count(void)
 {
-#ifdef MODULE
        MOD_INC_USE_COUNT;
-#endif
 }
 
 void parport_uss720_dec_use_count(void)
 {
-#ifdef MODULE
        MOD_DEC_USE_COUNT;
-#endif
 }
 
 /* --------------------------------------------------------------------- */
index 266e7bf..3ac27df 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: inode-v23.c,v 1.34 2000/08/10 08:58:00 dwmw2 Exp $
+ * $Id: inode-v23.c,v 1.43 2000/08/22 08:00:22 dwmw2 Exp $
  *
  *
  * Ported to Linux 2.3.x and MTD:
@@ -151,10+151,9 @@ jffs_put_super(struct super_block *sb)
 
        D2(printk("jffs_put_super()\n"));
 
-       D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
        if (c->gc_task) {
-               send_sig(SIGQUIT, c->gc_task, 1);
-               send_sig(SIGCONT, c->gc_task, 1);
+               D1(printk (KERN_NOTICE "jffs_put_super(): Telling gc thread to die.\n"));
+               send_sig(SIGKILL, c->gc_task, 1);
        }
        down (&c->gc_thread_sem);
 
@@ -179,54+178,56 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
        struct jffs_fmcontrol *fmc;
        struct jffs_file *f;
        struct jffs_node *new_node;
-       char *name = 0;
        int update_all;
        int res;
+       int recoverable = 0;
+
+       if ((res = inode_change_ok(inode, iattr)))
+               return res;
+
+       c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
+       fmc = c->fmc;
+
+       D3(printk (KERN_NOTICE "notify_change(): down biglock\n"));
+       down(&fmc->biglock);
+
+       f = jffs_find_file(c, inode->i_ino);
 
-       f = (struct jffs_file *)inode->u.generic_ip;
        ASSERT(if (!f) {
                printk("jffs_setattr(): Invalid inode number: %lu\n",
                       inode->i_ino);
-               return -1;
+               D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
+               up(&fmc->biglock);
+               return -EINVAL;
        });
 
        D1(printk("***jffs_setattr(): file: \"%s\", ino: %u\n",
                  f->name, f->ino));
 
-       c = f->c;
-       fmc = c->fmc;
        update_all = iattr->ia_valid & ATTR_FORCE;
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               if ( (update_all || iattr->ia_valid & ATTR_SIZE)
-                    && (iattr->ia_size < f->size) ) {
-                       /* See this case where someone is trying to
-                          shrink the size of a file as an exception.
-                          Accept it.  */
-                       /* TODO: Might just shrink it a bit?
-                          check f->size - ia_size */
-               } else {
-                       D1(printk("jffs_setattr(): Free size = %u\n",
-                                 jffs_free_size1(fmc)
-                                 + jffs_free_size2(fmc)));
-                       D(printk(KERN_NOTICE "JFFS: No space left on "
-                                "device\n"));
-                       return -ENOSPC;
-               }
-       }
+       if ( (update_all || iattr->ia_valid & ATTR_SIZE)
+            && (iattr->ia_size + 128 < f->size) ) {
+               /* We're shrinking the file by more than 128 bytes.
+                  We'll be able to GC and recover this space, so
+                  allow it to go into the reserved space. */
+               recoverable = 1;
+        }
 
        if (!(new_node = (struct jffs_node *)
                         kmalloc(sizeof(struct jffs_node), GFP_KERNEL))) {
                D(printk("jffs_setattr(): Allocation failed!\n"));
+               D3(printk (KERN_NOTICE "notify_change(): up biglock\n"));
+               up(&fmc->biglock);
                return -ENOMEM;
        }
+
        DJM(no_jffs_node++);
        new_node->data_offset = 0;
        new_node->removed_size = 0;
        raw_inode.magic = JFFS_MAGIC_BITMASK;
        raw_inode.ino = f->ino;
        raw_inode.pino = f->pino;
-       raw_inode.version = f->highest_version + 1;
        raw_inode.mode = f->mode;
        raw_inode.uid = f->uid;
        raw_inode.gid = f->gid;
@@ -237,7+238,7 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
        raw_inode.offset = 0;
        raw_inode.rsize = 0;
        raw_inode.dsize = 0;
-       raw_inode.nsize = 0;
+       raw_inode.nsize = f->nsize;
        raw_inode.nlink = f->nlink;
        raw_inode.spare = 0;
        raw_inode.rename = 0;
@@ -278,12+279,8 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
                new_node->data_offset = iattr->ia_size;
                new_node->removed_size = len;
                inode->i_size = iattr->ia_size;
+               inode->i_blocks = (inode->i_size + 511) >> 9;
 
-               /* If we truncate a file we want to add the name.  If we
-                  always do that, we could perhaps free more space on
-                  the flash (and besides it doesn't hurt).  */
-               name = f->name;
-               raw_inode.nsize = f->nsize;
                if (len) {
                        invalidate_inode_pages(inode);
                }
@@ -304,17+301,20 @@ jffs_setattr(struct dentry *dentry, struct iattr *iattr)
        }
 
        /* Write this node to the flash.  */
-       if ((res = jffs_write_node(c, new_node, &raw_inode, name, 0)) < 0) {
+       if ((res = jffs_write_node(c, new_node, &raw_inode, f->name, 0, recoverable, f)) < 0) {
                D(printk("jffs_notify_change(): The write failed!\n"));
                kfree(new_node);
                DJM(no_jffs_node--);
+               D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
+               up(&c->fmc->biglock);
                return res;
        }
 
        jffs_insert_node(c, f, &raw_inode, 0, new_node);
 
        mark_inode_dirty(inode);
-
+       D3(printk (KERN_NOTICE "n_c(): up biglock\n"));
+       up(&c->fmc->biglock);
        return 0;
 } /* jffs_notify_change()  */
 
@@ -403,7+403,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        __u32 rename_data = 0;
 
        D2(printk("***jffs_rename()\n"));
-
+       
        D(printk("jffs_rename(): old_dir: 0x%p, old name: 0x%p, "
                 "new_dir: 0x%p, new name: 0x%p\n",
                 old_dir, old_dentry->d_name.name,
@@ -413,17+413,9 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        ASSERT(if (!c) {
                printk(KERN_ERR "jffs_rename(): The old_dir inode "
                       "didn't have a reference to a jffs_file struct\n");
-               return -1;
+               return -EIO;
        });
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_rename(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               return -ENOSPC;
-       }
-
-       /* Find the old directory.  */
        result = -ENOTDIR;
        if (!(old_dir_f = (struct jffs_file *)old_dir->u.generic_ip)) {
                D(printk("jffs_rename(): Old dir invalid.\n"));
@@ -443,7+435,8 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
                D(printk("jffs_rename(): New dir invalid.\n"));
                goto jffs_rename_end;
        }
-
+       D3(printk (KERN_NOTICE "rename(): down biglock\n"));
+       down(&c->fmc->biglock);
        /* Create a node and initialize as much as needed.  */
        result = -ENOMEM;
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
@@ -459,7+452,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        raw_inode.magic = JFFS_MAGIC_BITMASK;
        raw_inode.ino = f->ino;
        raw_inode.pino = new_dir_f->ino;
-       raw_inode.version = f->highest_version + 1;
+/*     raw_inode.version = f->highest_version + 1; */
        raw_inode.mode = f->mode;
        raw_inode.uid = current->fsuid;
        raw_inode.gid = current->fsgid;
@@ -491,7+484,7 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        /* Write the new node to the flash memory.  */
        if ((result = jffs_write_node(c, node, &raw_inode,
                                      new_dentry->d_name.name,
-                                     (unsigned char*)&rename_data)) < 0) {
+                                     (unsigned char*)&rename_data, 0, f)) < 0) {
                D(printk("jffs_rename(): Failed to write node to flash.\n"));
                kfree(node);
                DJM(no_jffs_node--);
@@ -501,14+494,14 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        if (raw_inode.rename) {
                /* The file with the same name must be deleted.  */
-               down(&c->fmc->gclock);
+               //FIXME deadlock                down(&c->fmc->gclock);
                if ((result = jffs_remove(new_dir, new_dentry,
                                          del_f->mode)) < 0) {
                        /* This is really bad.  */
                        printk(KERN_ERR "JFFS: An error occurred in "
                               "rename().\n");
                }
-               up(&c->fmc->gclock);
+               //              up(&c->fmc->gclock);
        }
 
        if (old_dir_f != new_dir_f) {
@@ -539,6+532,8 @@ jffs_rename(struct inode *old_dir, struct dentry *old_dentry,
        }
 
 jffs_rename_end:
+       D3(printk (KERN_NOTICE "rename(): up biglock\n"));
+       up(&c->fmc->biglock);
        return result;
 } /* jffs_rename()  */
 
@@ -551,13+546,18 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct jffs_file *f;
        struct dentry *dentry = filp->f_dentry;
        struct inode *inode = dentry->d_inode;
+       struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
        int j;
        int ddino;
+       D3(printk (KERN_NOTICE "readdir(): down biglock\n"));
+       down(&c->fmc->biglock);
 
        D2(printk("jffs_readdir(): inode: 0x%p, filp: 0x%p\n", inode, filp));
        if (filp->f_pos == 0) {
                D3(printk("jffs_readdir(): \".\" %lu\n", inode->i_ino));
                if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
+                 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
+                       up(&c->fmc->biglock);
                        return 0;
                }
                filp->f_pos = 1;
@@ -571,8+571,11 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                                 inode->u.generic_ip)->pino;
                }
                D3(printk("jffs_readdir(): \"..\" %u\n", ddino));
-               if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0)
+               if (filldir(dirent, "..", 2, filp->f_pos, ddino, DT_DIR) < 0) {
+                 D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
+                       up(&c->fmc->biglock);
                        return 0;
+               }
                filp->f_pos++;
        }
        f = ((struct jffs_file *)inode->u.generic_ip)->children;
@@ -583,11+586,15 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                D3(printk("jffs_readdir(): \"%s\" ino: %u\n",
                          (f->name ? f->name : ""), f->ino));
                if (filldir(dirent, f->name, f->nsize,
-                           filp->f_pos , f->ino, DT_UNKNOWN) < 0)
+                           filp->f_pos , f->ino, DT_UNKNOWN) < 0) {
+                       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
+                       up(&c->fmc->biglock);
                        return 0;
+               }
                filp->f_pos++;
        }
-
+       D3(printk (KERN_NOTICE "readdir(): up biglock\n"));
+       up(&c->fmc->biglock);
        return filp->f_pos;
 } /* jffs_readdir()  */
 
@@ -599,6+606,7 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
 {
        struct jffs_file *d;
        struct jffs_file *f;
+       struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp;
        int len;
        int r = 0;
        const char *name;
@@ -615,6+623,9 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
                kfree(s);
        });
 
+       D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
+       down(&c->fmc->biglock);
+
        r = -ENAMETOOLONG;
        if (len > JFFS_MAX_NAME_LEN) {
                goto jffs_lookup_end;
@@ -628,21+639,39 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
        }
 
        /* Get the corresponding inode to the file.  */
+
+       /* iget calls jffs_read_inode, so we need to drop the biglock
+           before calling iget.  Unfortunately, the GC has a tendency
+           to sneak in here, because iget sometimes calls schedule (). 
+         */
+
        if ((len == 1) && (name[0] == '.')) {
+                D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
+               up(&c->fmc->biglock);
                if (!(inode = iget(dir->i_sb, d->ino))) {
                        D(printk("jffs_lookup(): . iget() ==> NULL\n"));
-                       goto jffs_lookup_end;
+                       goto jffs_lookup_end_no_biglock;
                }
+               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
+               down(&c->fmc->biglock);
        } else if ((len == 2) && (name[0] == '.') && (name[1] == '.')) {
-               if (!(inode = iget(dir->i_sb, d->pino))) {
+               D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
+               up(&c->fmc->biglock);
+               if (!(inode = iget(dir->i_sb, d->pino))) {
                        D(printk("jffs_lookup(): .. iget() ==> NULL\n"));
-                       goto jffs_lookup_end;
+                       goto jffs_lookup_end_no_biglock;
                }
+               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
+               down(&c->fmc->biglock);
        } else if ((f = jffs_find_child(d, name, len))) {
+               D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
+               up(&c->fmc->biglock);
                if (!(inode = iget(dir->i_sb, f->ino))) {
                        D(printk("jffs_lookup(): iget() ==> NULL\n"));
-                       goto jffs_lookup_end;
+                       goto jffs_lookup_end_no_biglock;
                }
+               D3(printk (KERN_NOTICE "lookup(): down biglock\n"));
+               down(&c->fmc->biglock);
        } else {
                D3(printk("jffs_lookup(): Couldn't find the file. "
                          "f = 0x%p, name = \"%s\", d = 0x%p, d->ino = %u\n",
@@ -651,9+680,15 @@ jffs_lookup(struct inode *dir, struct dentry *dentry)
        }
 
        d_add(dentry, inode);
+       D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
+       up(&c->fmc->biglock);
        return NULL;
 
 jffs_lookup_end:
+       D3(printk (KERN_NOTICE "lookup(): up biglock\n"));
+       up(&c->fmc->biglock);
+
+jffs_lookup_end_no_biglock:
        return ERR_PTR(r);
 } /* jffs_lookup()  */
 
@@ -667,6+702,7 @@ jffs_readpage(struct file *file, struct page *page)
        int result = -EIO;
        struct inode *inode = (struct inode*)page->mapping->host;
        struct jffs_file *f = (struct jffs_file *)inode->u.generic_ip;
+       struct jffs_control *c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
        int r;
        loff_t offset;
 
@@ -679,6+715,9 @@ jffs_readpage(struct file *file, struct page *page)
        ClearPageUptodate(page);
        ClearPageError(page);
 
+       D3(printk (KERN_NOTICE "readpage(): down biglock\n"));
+       down(&c->fmc->biglock);
+
        offset = page->index << PAGE_CACHE_SHIFT;
        if (offset < inode->i_size) {
                read_len = jffs_min(inode->i_size - offset, PAGE_SIZE);
@@ -697,6+736,10 @@ jffs_readpage(struct file *file, struct page *page)
                               "read %d bytes.\n", read_len, r);
                });
        }
+
+       D3(printk (KERN_NOTICE "readpage(): up biglock\n"));
+       up(&c->fmc->biglock);
+       
        if (result) {
                memset(buf, 0, PAGE_SIZE);
                SetPageError(page);
@@ -737,22+780,16 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
        });
 
        dir_f = (struct jffs_file *)dir->u.generic_ip;
+
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_mkdir(): No reference to a "
                       "jffs_file struct in inode.\n");
-               result = -1;
-               goto jffs_mkdir_end;
+               return -EIO;
        });
 
        c = dir_f->c;
-
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_mkdir(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               result = -ENOSPC;
-               goto jffs_mkdir_end;
-       }
+       D3(printk (KERN_NOTICE "mkdir(): down biglock\n"));
+       down(&c->fmc->biglock);
 
        dir_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX)
                              & ~current->fs->umask);
@@ -794,7+831,7 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        /* Write the new node to the flash.  */
        if ((result = jffs_write_node(c, node, &raw_inode,
-                                     dentry->d_name.name, 0)) < 0) {
+                                     dentry->d_name.name, 0, 0, NULL)) < 0) {
                D(printk("jffs_mkdir(): jffs_write_node() failed.\n"));
                kfree(node);
                DJM(no_jffs_node--);
@@ -821,6+858,8 @@ jffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
        result = 0;
 jffs_mkdir_end:
+       D3(printk (KERN_NOTICE "mkdir(): up biglock\n"));
+       up(&c->fmc->biglock);
        return result;
 } /* jffs_mkdir()  */
 
@@ -829,8+868,15 @@ jffs_mkdir_end:
 static int
 jffs_rmdir(struct inode *dir, struct dentry *dentry)
 {
+       struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp;
+       int ret;
        D3(printk("***jffs_rmdir()\n"));
-       return jffs_remove(dir, dentry, S_IFDIR);
+       D3(printk (KERN_NOTICE "rmdir(): down biglock\n"));
+       down(&c->fmc->biglock);
+       ret = jffs_remove(dir, dentry, S_IFDIR);
+       D3(printk (KERN_NOTICE "rmdir(): up biglock\n"));
+       up(&c->fmc->biglock);
+       return ret;
 }
 
 
@@ -838,8+884,16 @@ jffs_rmdir(struct inode *dir, struct dentry *dentry)
 static int
 jffs_unlink(struct inode *dir, struct dentry *dentry)
 {
+       struct jffs_control *c = (struct jffs_control *)dir->i_sb->u.generic_sbp;
+       int ret; 
+
        D3(printk("***jffs_unlink()\n"));
-       return jffs_remove(dir, dentry, 0);
+       D3(printk (KERN_NOTICE "unlink(): down biglock\n"));
+       down(&c->fmc->biglock);
+       ret = jffs_remove(dir, dentry, 0);
+       D3(printk (KERN_NOTICE "unlink(): up biglock\n"));
+       up(&c->fmc->biglock);
+       return ret;
 }
 
 
@@ -862,7+916,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
                char *_name = (char *) kmalloc(len + 1, GFP_KERNEL);
                memcpy(_name, name, len);
                _name[len] = '\0';
-               printk("***jffs_remove(): file = \"%s\"\n", _name);
+               printk("***jffs_remove(): file = \"%s\", ino = %ld\n", _name, dentry->d_inode->i_ino);
                kfree(_name);
        });
 
@@ -916,7+970,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
        raw_inode.magic = JFFS_MAGIC_BITMASK;
        raw_inode.ino = del_f->ino;
        raw_inode.pino = del_f->pino;
-       raw_inode.version = del_f->highest_version + 1;
+/*     raw_inode.version = del_f->highest_version + 1; */
        raw_inode.mode = del_f->mode;
        raw_inode.uid = current->fsuid;
        raw_inode.gid = current->fsgid;
@@ -933,7+987,7 @@ jffs_remove(struct inode *dir, struct dentry *dentry, int type)
        raw_inode.deleted = 1;
 
        /* Write the new node to the flash memory.  */
-       if (jffs_write_node(c, del_node, &raw_inode, 0, 0) < 0) {
+       if (jffs_write_node(c, del_node, &raw_inode, 0, 0, 1, del_f) < 0) {
                kfree(del_node);
                DJM(no_jffs_node--);
                result = -EIO;
@@ -979,13+1033,8 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
        dir_f = (struct jffs_file *)dir->u.generic_ip;
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_mknod(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               result = -ENOSPC;
-               goto jffs_mknod_end;
-       }
+       D3(printk (KERN_NOTICE "mknod(): down biglock\n"));
+       down(&c->fmc->biglock);
 
        /* Create and initialize a new node.  */
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
@@ -1021,7+1070,7 @@ jffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int rdev)
 
        /* Write the new node to the flash.  */
        if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-                                 (unsigned char *)&dev)) < 0) {
+                                 (unsigned char *)&dev, 0, NULL)) < 0) {
                D(printk("jffs_mknod(): jffs_write_node() failed.\n"));
                result = err;
                goto jffs_mknod_err;
@@ -1053,6+1102,8 @@ jffs_mknod_err:
        }
 
 jffs_mknod_end:
+       D3(printk (KERN_NOTICE "mknod(): up biglock\n"));
+       up(&c->fmc->biglock);
        return result;
 } /* jffs_mknod()  */
 
@@ -1088,24+1139,20 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_symlink(): No reference to a "
                       "jffs_file struct in inode.\n");
-               return -1;
+               return -EIO;
        });
 
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_symlink(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               return -ENOSPC;
-       }
-
        /* Create a node and initialize it as much as needed.  */
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
                                                  GFP_KERNEL))) {
                D(printk("jffs_symlink(): Allocation failed: node = NULL\n"));
                return -ENOMEM;
        }
+       D3(printk (KERN_NOTICE "symlink(): down biglock\n"));
+       down(&c->fmc->biglock);
+
        DJM(no_jffs_node++);
        node->data_offset = 0;
        node->removed_size = 0;
@@ -1132,30+1179,32 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
 
        /* Write the new node to the flash.  */
        if ((err = jffs_write_node(c, node, &raw_inode, dentry->d_name.name,
-                                  (const unsigned char *)symname)) < 0) {
+                                  (const unsigned char *)symname, 0, NULL)) < 0) {
                D(printk("jffs_symlink(): jffs_write_node() failed.\n"));
                kfree(node);
                DJM(no_jffs_node--);
-               return err;
+               goto jffs_symlink_end;
        }
 
        /* Insert the new node into the file system.  */
        if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
                                    node)) < 0) {
-               return err;
+               goto jffs_symlink_end;
        }
 
        inode = jffs_new_inode(dir, &raw_inode, &err);
        if (inode == NULL) {
-               return err;
+               goto jffs_symlink_end;
        }
-
+       err = 0;
        inode->i_op = &page_symlink_inode_operations;
        inode->i_mapping->a_ops = &jffs_address_operations;
 
        d_instantiate(dentry, inode);
-
-       return 0;
+ jffs_symlink_end:
+       D3(printk (KERN_NOTICE "symlink(): up biglock\n"));
+       up(&c->fmc->biglock);
+       return err;
 } /* jffs_symlink()  */
 
 
@@ -1191,24+1240,20 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
        ASSERT(if (!dir_f) {
                printk(KERN_ERR "jffs_create(): No reference to a "
                       "jffs_file struct in inode.\n");
-               return -1;
+               return -EIO;
        });
 
        c = dir_f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_create(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               return -ENOSPC;
-       }
-
        /* Create a node and initialize as much as needed.  */
        if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
                                                  GFP_KERNEL))) {
                D(printk("jffs_create(): Allocation failed: node == 0\n"));
                return -ENOMEM;
        }
+       D3(printk (KERN_NOTICE "create(): down biglock\n"));
+       down(&c->fmc->biglock);
+
        DJM(no_jffs_node++);
        node->data_offset = 0;
        node->removed_size = 0;
@@ -1235,33+1280,35 @@ jffs_create(struct inode *dir, struct dentry *dentry, int mode)
 
        /* Write the new node to the flash.  */
        if ((err = jffs_write_node(c, node, &raw_inode,
-                                  dentry->d_name.name, 0)) < 0) {
+                                  dentry->d_name.name, 0, 0, NULL)) < 0) {
                D(printk("jffs_create(): jffs_write_node() failed.\n"));
                kfree(node);
                DJM(no_jffs_node--);
-               return err;
+               goto jffs_create_end;
        }
 
        /* Insert the new node into the file system.  */
        if ((err = jffs_insert_node(c, 0, &raw_inode, dentry->d_name.name,
                                    node)) < 0) {
-               return err;
+               goto jffs_create_end;
        }
 
        /* Initialize an inode.  */
        inode = jffs_new_inode(dir, &raw_inode, &err);
        if (inode == NULL) {
-               return err;
+               goto jffs_create_end;
        }
-
+       err = 0;
        inode->i_op = &jffs_file_inode_operations;
        inode->i_fop = &jffs_file_operations;
        inode->i_mapping->a_ops = &jffs_address_operations;
        inode->i_mapping->nrpages = 0;
 
        d_instantiate(dentry, inode);
-
-       return 0;
+ jffs_create_end:
+       D3(printk (KERN_NOTICE "create(): up biglock\n"));
+       up(&c->fmc->biglock);
+       return err;
 } /* jffs_create()  */
 
 
@@ -1277,7+1324,9 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
        struct dentry *dentry = filp->f_dentry;
        struct inode *inode = dentry->d_inode;
        unsigned char *vbuf;
-       int written = 0;
+       int recoverable = 0;
+       size_t written = 0;
+       __u32 thiscount = count;
        loff_t pos;
        int err;
 
@@ -1287,147+1336,176 @@ jffs_file_write(struct file *filp, const char *buf, size_t count,
                  "filp: 0x%p, buf: 0x%p, count: %d\n",
                  inode, inode->i_ino, filp, buf, count));
 
-       down(&inode->i_sem);
-
-       pos = *ppos;
-       err = -EINVAL;
-       if (pos < 0)
-               goto out;
-
        err = filp->f_error;
        if (err) {
                filp->f_error = 0;
-               goto out;
+               return err;
        }
 
+       down(&inode->i_sem);
+
        if (inode->i_sb->s_flags & MS_RDONLY) {
                D(printk("jffs_file_write(): MS_RDONLY\n"));
-               err = -ENOSPC;
-               goto out;
+               err = -EROFS;
+               goto out_isem;
        }
 
+       err = -EINVAL;
+
        if (!S_ISREG(inode->i_mode)) {
                D(printk("jffs_file_write(): inode->i_mode == 0x%08x\n",
                         inode->i_mode));
-               err = -EINVAL;
-               goto out;
+               goto out_isem;
        }
 
        if (!(f = (struct jffs_file *)inode->u.generic_ip)) {
                D(printk("jffs_file_write(): inode->u.generic_ip = 0x%p\n",
                         inode->u.generic_ip));
-               err = -EINVAL;
-               goto out;
+               goto out_isem;
        }
 
        c = f->c;
 
-       if (!JFFS_ENOUGH_SPACE(c)) {
-               D1(printk("jffs_file_write(): Free size = %u\n",
-                         jffs_free_size1(c->fmc) + jffs_free_size2(c->fmc)));
-               D(printk(KERN_NOTICE "JFFS: No space left on device\n"));
-               err = -ENOSPC;
-               goto out;
-       }
-
        if (filp->f_flags & O_APPEND)
                pos = inode->i_size;
+       else
+               pos = *ppos;
+       
+       if (pos < 0) {
+               goto out_isem;
+       }
+       
+       thiscount = jffs_min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
 
-
-       if (!(vbuf = kmalloc(count, GFP_KERNEL))) {
+       if (!(vbuf = kmalloc(thiscount, GFP_KERNEL))) {
                D(printk("jffs_file_write(): failed to allocate bounce buffer. Fix me to use page cache\n"));
                err = -ENOMEM;
-               goto out;
+               goto out_isem;
        }
 
-       /* FIXME: This is entirely gratuitous use of bounce buffers.
-          Get a clue and use the page cache. 
-          /me wanders off to get a crash course on Linux VFS
-          dwmw2
-       */
-       if (copy_from_user(vbuf, buf, count)) {
-               kfree(vbuf);
-               return -EFAULT;
-       }
-               
-
-       /* Things are going to be written so we could allocate and
-          initialize the necessary data structures now.  */
-       if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
-                                                 GFP_KERNEL))) {
-               D(printk("jffs_file_write(): node == 0\n"));
-               err = -ENOMEM;
-               kfree(vbuf);
-               goto out;
-       }
-       DJM(no_jffs_node++);
-       node->data_offset = pos;
-       node->removed_size = 0;
+       D3(printk (KERN_NOTICE "file_write(): down biglock\n"));
+       down(&c->fmc->biglock);
 
-       /* Initialize the raw inode.  */
-       raw_inode.magic = JFFS_MAGIC_BITMASK;
-       raw_inode.ino = f->ino;
-       raw_inode.pino = f->pino;
-       raw_inode.version = f->highest_version + 1;
-       raw_inode.mode = f->mode;
+       /* Urgh. POSIX says we can do short writes if we feel like it. 
+        * In practice, we can't. Nothing will cope. So we loop until
+        * we're done.
+        *
+        * <_Anarchy_> posix and reality are not interconnected on this issue
+        */
+       while (count) {
+
+               /* FIXME: This is entirely gratuitous use of bounce buffers.
+                  Get a clue and use the page cache. 
+                  /me wanders off to get a crash course on Linux VFS
+                  dwmw2
+               */
+               if (copy_from_user(vbuf, buf, thiscount)) {
+                       err = -EFAULT;
+                       goto out;
+               }
+               
+               /* Things are going to be written so we could allocate and
+                  initialize the necessary data structures now.  */
+               if (!(node = (struct jffs_node *) kmalloc(sizeof(struct jffs_node),
+                                                         GFP_KERNEL))) {
+                       D(printk("jffs_file_write(): node == 0\n"));
+                       err = -ENOMEM;
+                       goto out;
+               }
+               DJM(no_jffs_node++);
+               
+               node->data_offset = pos;
+               node->removed_size = 0;
+               
+               /* Initialize the raw inode.  */
+               raw_inode.magic = JFFS_MAGIC_BITMASK;
+               raw_inode.ino = f->ino;
+               raw_inode.pino = f->pino;
 
-       raw_inode.uid = f->uid;
-       raw_inode.gid = f->gid;
-       /*
-       raw_inode.uid = current->fsuid;
-       raw_inode.gid = current->fsgid;
-       */
-       raw_inode.atime = CURRENT_TIME;
-       raw_inode.mtime = raw_inode.atime;
-       raw_inode.ctime = f->ctime;
-       raw_inode.offset = pos;
-       raw_inode.dsize = count;
-       raw_inode.rsize = 0;
-       raw_inode.nsize = 0;
-       raw_inode.nlink = f->nlink;
-       raw_inode.spare = 0;
-       raw_inode.rename = 0;
-       raw_inode.deleted = 0;
+               raw_inode.mode = f->mode;
+               
+               raw_inode.uid = f->uid;
+               raw_inode.gid = f->gid;
+               raw_inode.atime = CURRENT_TIME;
+               raw_inode.mtime = raw_inode.atime;
+               raw_inode.ctime = f->ctime;
+               raw_inode.offset = pos;
+               raw_inode.dsize = thiscount;
+               raw_inode.rsize = 0;
+               raw_inode.nsize = f->nsize;
+               raw_inode.nlink = f->nlink;
+               raw_inode.spare = 0;
+               raw_inode.rename = 0;
+               raw_inode.deleted = 0;
+               
+               if (pos < f->size) {
+                       node->removed_size = raw_inode.rsize = jffs_min(thiscount, f->size - pos);
+                       
+                       /* If this node is going entirely over the top of old data, 
+                          we can allow it to go into the reserved space, because 
+                          we can that GC can reclaim the space later.
+                       */
+                       if (pos + thiscount < f->size) {
+                               /* If all the data we're overwriting are _real_,
+                                  not just holes, then:
+                                  recoverable = 1;
+                               */
+                       }
+               }
+               
+               /* Write the new node to the flash.  */
+               /* NOTE: We would be quite happy if jffs_write_node() wrote a 
+                  smaller node than we were expecting. There's no need for it 
+                  to waste the space at the end of the flash just because it's 
+                  a little smaller than what we asked for. But that's a whole
+                  new can of worms which I'm not going to open this week. dwmw2.
+               */
+               if ((err = jffs_write_node(c, node, &raw_inode, f->name,
+                                          (const unsigned char *)vbuf,
+                                          recoverable, f)) < 0) {
+                       D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
+                       kfree(node);
+                       DJM(no_jffs_node--);
+                       goto out;
+               }
 
-       if (pos < f->size) {
-               node->removed_size = raw_inode.rsize = jffs_min(count, f->size - pos);
-       }
+               written += err;
+               buf += err;
+               count -= err;
+               pos += err;
 
-       /* Write the new node to the flash.  */
-       if ((written = jffs_write_node(c, node, &raw_inode, 0,
-                                      (const unsigned char *)vbuf)) < 0) {
-               D(printk("jffs_file_write(): jffs_write_node() failed.\n"));
-               kfree(node);
-               kfree(vbuf);
-               DJM(no_jffs_node--);
-               err = written;
-               goto out;
-       }
+               /* Insert the new node into the file system.  */
+               if ((err = jffs_insert_node(c, f, &raw_inode, 0, node)) < 0) {
+                       goto out;
+               }
 
-       kfree(vbuf);
+               D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
 
-       /* Insert the new node into the file system.  */
-       if ((err = jffs_insert_node(c, f, &raw_inode, 0, node)) < 0) {
-               goto out;
+               thiscount = jffs_min(c->fmc->max_chunk_size - sizeof(struct jffs_raw_inode), count);
        }
-
-       pos += written;
+ out:
+       D3(printk (KERN_NOTICE "file_write(): up biglock\n"));
+       up(&c->fmc->biglock);
        *ppos = pos;
-
-       D3(printk("jffs_file_write(): new f_pos %ld.\n", (long)pos));
+       kfree(vbuf);
 
        /* Fix things in the real inode.  */
        if (pos > inode->i_size) {
                inode->i_size = pos;
+               inode->i_blocks = (inode->i_size + 511) >> 9;
        }
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        mark_inode_dirty(inode);
        invalidate_inode_pages(inode);
 
-       err = written;
-out:
+ out_isem:
        up(&inode->i_sem);
-       return err;
+       
+       /* What if there was an error, _and_ we've written some data. */
+       if (written)
+               return written;
+       else
+               return err;
 } /* jffs_file_write()  */
 
 
@@ -1437,6+1515,7 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
           unsigned long arg)
 {
        struct jffs_control *c;
+       int ret = 0;
 
        D2(printk("***jffs_ioctl(): cmd = 0x%08x, arg = 0x%08lx\n",
                  cmd, arg));
@@ -1446,6+1525,8 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                       "(cmd = 0x%08x)\n", cmd);
                return -EIO;
        }
+       D3(printk (KERN_NOTICE "ioctl(): down biglock\n"));
+       down(&c->fmc->biglock);
 
        switch (cmd) {
        case JFFS_PRINT_HASH:
@@ -1464,7+1545,8 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                                       sizeof(struct jffs_flash_status))) {
                                D(printk("jffs_ioctl(): Bad arg in "
                                         "JFFS_GET_STATUS ioctl!\n"));
-                               return -EFAULT;
+                               ret = -EFAULT;
+                               break;
                        }
                        fst.size = fmc->flash_size;
                        fst.used = fmc->used_size;
@@ -1478,15+1560,16 @@ jffs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        if (copy_to_user((struct jffs_flash_status *)arg,
                                         &fst,
                                         sizeof(struct jffs_flash_status))) {
-                         return -EFAULT;
+                         ret = -EFAULT;
                        }
                }
                break;
        default:
-               return -ENOTTY;
+               ret = -ENOTTY;
        }
-
-       return 0;
+       D3(printk (KERN_NOTICE "ioctl(): up biglock\n"));
+       up(&c->fmc->biglock);
+       return ret;
 } /* jffs_ioctl()  */
 
 
@@ -1555,9+1638,13 @@ jffs_read_inode(struct inode *inode)
                return;
        }
        c = (struct jffs_control *)inode->i_sb->u.generic_sbp;
+       D3(printk (KERN_NOTICE "read_inode(): down biglock\n"));
+       down(&c->fmc->biglock);
        if (!(f = jffs_find_file(c, inode->i_ino))) {
                D(printk("jffs_read_inode(): No such inode (%lu).\n",
                         inode->i_ino));
+               D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
+               up(&c->fmc->biglock);
                return;
        }
        inode->u.generic_ip = (void *)f;
@@ -1592,6+1679,8 @@ jffs_read_inode(struct inode *inode)
                jffs_read_data(f, (char *)&rdev, 0, sizeof(kdev_t));
                init_special_inode(inode, inode->i_mode, kdev_t_to_nr(rdev));
        }
+       D3(printk (KERN_NOTICE "read_inode(): up biglock\n"));
+       up(&c->fmc->biglock);
 }
 
 
@@ -1603,6+1692,7 @@ jffs_delete_inode(struct inode *inode)
 
        lock_kernel();
        inode->i_size = 0;
+       inode->i_blocks = 0;
        clear_inode(inode);
        unlock_kernel();
 }
index adb2e0c..5cf82f4 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: intrep.c,v 1.39 2000/08/09 13:23:36 dwmw2 Exp $
+ * $Id: intrep.c,v 1.69 2000/08/24 09:35:47 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
@@ -191,12+191,13 @@ flash_safe_read(struct mtd_info *mtd, loff_t from,
                u_char *buf, size_t count)
 {
        size_t retlen;
+       int res;
 
-       MTD_READ(mtd, from, count, &retlen, buf);
+       res = MTD_READ(mtd, from, count, &retlen, buf);
        if (retlen != count) {
-               printk("Didn't read all bytes in flash_safe_read()\n");
+               printk("Didn't read all bytes in flash_safe_read(). Returned %d\n", res);
        }
-       return retlen;
+       return res?res:retlen;
 }
 
 
@@ -205,10+206,11 @@ flash_read_u32(struct mtd_info *mtd, loff_t from)
 {
        size_t retlen;
        __u32 ret;
+       int res;
 
-       MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
+       res = MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret);
        if (retlen != 4) {
-               printk("Didn't read all bytes in flash_read_u32()\n");
+               printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res);
                return 0;
        }
 
@@ -221,10+223,11 @@ flash_read_u8(struct mtd_info *mtd, loff_t from)
 {
        size_t retlen;
        __u8 ret;
+       int res;
 
-       MTD_READ(mtd, from, 1, &retlen, &ret);
+       res = MTD_READ(mtd, from, 1, &retlen, &ret);
        if (retlen != 1) {
-               printk("Didn't read a byte in flash_read_u8()\n");
+               printk("Didn't read a byte in flash_read_u8(). Returned %d\n", res);
                return 0;
        }
 
@@ -237,12+240,13 @@ flash_safe_write(struct mtd_info *mtd, loff_t to,
                 const u_char *buf, size_t count)
 {
        size_t retlen;
+       int res;
 
-       MTD_WRITE(mtd, to, count, &retlen, buf);
+       res = MTD_WRITE(mtd, to, count, &retlen, buf);
        if (retlen != count) {
-               printk("Didn't write all bytes in flash_safe_write()\n");
+               printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res);
        }
-       return retlen;
+       return res?res:retlen;
 }
 
 
@@ -306,7+310,8 @@ flash_erase_region(struct mtd_info *mtd, loff_t start,
        erase->len = size;
        erase->priv = (u_long)&wait_q;
 
-       set_current_state(TASK_INTERRUPTIBLE);
+       /* FIXME: Use TASK_INTERRUPTIBLE and deal with being interrupted */
+       set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue(&wait_q, &wait);
 
        if (MTD_ERASE(mtd, erase) < 0) {
@@ -321,7+326,6 @@ flash_erase_region(struct mtd_info *mtd, loff_t start,
        }
 
        schedule(); /* Wait for flash to finish. */
-       /* FIXME: We could have been interrupted here. We don't deal with it */
        remove_wait_queue(&wait_q, &wait);
 
        kfree(erase);
@@ -369,15+373,14 @@ jffs_checksum_flash(struct mtd_info *mtd, loff_t start, int size)
        D3(printk("checksum result: 0x%08x\n", sum));
        return sum;
 }
-
 static __inline__ void jffs_fm_write_lock(struct jffs_fmcontrol *fmc)
 {
-       down(&fmc->wlock);
+  //   down(&fmc->wlock);
 }
 
 static __inline__ void jffs_fm_write_unlock(struct jffs_fmcontrol *fmc)
 {
-       up(&fmc->wlock);
+  //   up(&fmc->wlock);
 }
 
 
@@ -421,6+424,7 @@ jffs_create_control(kdev_t dev)
        }
        DJM(no_jffs_control++);
        c->root = 0;
+       c->gc_task = 0;
        c->hash_len = JFFS_HASH_SIZE;
        s = sizeof(struct list_head) * c->hash_len;
        if (!(c->hash = (struct list_head *)kmalloc(s, GFP_KERNEL))) {
@@ -640,6+644,16 @@ jffs_scan_flash(struct jffs_control *c)
                           a single kernel thread will fix the original problem.
                        */
                        if ((__u32) pos % fmc->sector_size) {
+                               /* If there was free space in previous 
+                                  sectors, don't mark that dirty too - 
+                                  only from the beginning of this sector
+                                  (or from start) 
+                               */
+                               if (start < (pos & ~(fmc->sector_size-1))) {
+                                       D1(printk("Reducing start to 0x%x from 0x%x\n", pos & ~(fmc->sector_size-1), start));
+                                       start = pos & ~(fmc->sector_size-1);
+                               }
+                               D1(printk("Dirty space: 0x%x for 0x%x bytes\n", start, (pos - start)));
                                jffs_fmalloced(fmc, (__u32) start,
                                               (__u32) (pos - start), 0);
                        }
@@ -672,6+686,7 @@ jffs_scan_flash(struct jffs_control *c)
                                  "hexdump(pos = 0x%lx, len = 128):\n",
                                  (long)pos));
                        D1(jffs_hexdump(fmc->mtd, pos, 128));
+               cont_dirty:
                        for (pos += 4; pos < end; pos += 4) {
                                switch (flash_read_u32(fmc->mtd, pos)) {
                                case JFFS_MAGIC_BITMASK:
@@ -679,6+694,46 @@ jffs_scan_flash(struct jffs_control *c)
                                                       (__u32) (pos - start),
                                                       0);
                                        goto cont_scan;
+                               case JFFS_EMPTY_BITMASK:
+                                       /* First, mark as dirty the region
+                                          which really does contain crap. */
+                                       jffs_fmalloced(fmc, (__u32) start,
+                                                      (__u32) (pos - start),
+                                                      0);
+
+                                       /* Then, scan the region which looks free.
+                                          Depending on how large it is, we may
+                                          mark it dirty too.
+                                       */
+                                       start = pos;
+                                       for (; pos < end ; pos += 4) {
+                                               switch (flash_read_u32(fmc->mtd, pos)) {
+                                               case JFFS_MAGIC_BITMASK:
+                                                       if (pos - start < fmc->max_chunk_size) {
+                                                               /* Not much free space. Mark it dirty. */
+                                                               jffs_fmalloced(fmc, (__u32)start,
+                                                                              (__u32)pos-start, 0);
+                                                       }
+                                                       goto cont_scan;
+
+                                               case JFFS_EMPTY_BITMASK:
+                                                       /* More empty space */
+                                                       continue;
+                               
+                                               default: 
+                                                       /* i.e. more dirt */
+                                                       if (pos - start < fmc->max_chunk_size) {
+                                                               /* There wasn't much before the dirt
+                                                                  started again. Just mark it all dirty
+                                                               */
+                                                               goto cont_dirty;
+                                                       }
+                                                       /* There was quite a lot of free space. Leave it
+                                                          free.
+                                                       */
+                                                       goto cont_scan;
+                                               }
+                                       }
                                default:
                                        break;
                                }
@@ -734,6+789,8 @@ jffs_scan_flash(struct jffs_control *c)
                /* Check the raw inode read so far.  Start with the
                   maximum length of the filename.  */
                if (raw_inode.nsize > JFFS_MAX_NAME_LEN) {
+                       printk(KERN_WARNING "jffs_scan_flash: Found a "
+                              "JFFS node with name too large\n");
                        goto bad_inode;
                }
 
@@ -748,6+805,9 @@ jffs_scan_flash(struct jffs_control *c)
                /* The node's data segment should not exceed a
                   certain length.  */
                if (raw_inode.dsize > fmc->max_chunk_size) {
+                       printk(KERN_WARNING "jffs_scan_flash: Found a "
+                              "JFFS node with dsize (0x%x) > max_chunk_size (0x%x)\n",
+                              raw_inode.dsize, fmc->max_chunk_size);
                        goto bad_inode;
                }
 
@@ -895,9+955,9 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
        int insert_into_tree = 0;
 
        D2(printk("jffs_insert_node(): ino = %u, version = %u, "
-                 "name = \"%s\"\n",
+                 "name = \"%s\", deleted = %d\n",
                  raw_inode->ino, raw_inode->version,
-                 ((name && *name) ? name : "")));
+                 ((name && *name) ? name : ""), raw_inode->deleted));
 
        /* If there doesn't exist an associated jffs_file, then
           create, initialize and insert one into the file system.  */
@@ -908,7+968,6 @@ jffs_insert_node(struct jffs_control *c, struct jffs_file *f,
                jffs_insert_file_into_hash(f);
                insert_into_tree = 1;
        }
-
        node->ino = raw_inode->ino;
        node->version = raw_inode->version;
        node->data_size = raw_inode->dsize;
@@ -1345,18+1404,30 @@ jffs_write_dummy_node(struct jffs_control *c, struct jffs_fm *dirty_fm)
 int
 jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                struct jffs_raw_inode *raw_inode,
-               const char *name, const unsigned char *data)
+               const char *name, const unsigned char *data,
+               int recoverable,
+               struct jffs_file *f)
 {
        struct jffs_fmcontrol *fmc = c->fmc;
        struct jffs_fm *fm = NULL;
        __u32 pos;
        int err;
+       __u32 slack = 0;
+
        __u32 total_name_size = raw_inode->nsize
                                + JFFS_GET_PAD_BYTES(raw_inode->nsize);
        __u32 total_data_size = raw_inode->dsize
                                + JFFS_GET_PAD_BYTES(raw_inode->dsize);
        __u32 total_size = sizeof(struct jffs_raw_inode)
                           + total_name_size + total_data_size;
+       
+       /* If this node isn't something that will eventually let
+          GC free even more space, then don't allow it unless
+          there's at least max_chunk_size space still available
+       */
+       if (!recoverable)
+               slack = fmc->max_chunk_size;
+               
 
        /* Fire the retrorockets and shoot the fruiton torpedoes, sir!  */
 
@@ -1371,14+1442,22 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
        });
 
        D1(printk("jffs_write_node(): filename = \"%s\", ino = %u, "
-                 "version = %u, total_size = %u\n",
+                 "total_size = %u\n",
                  (name ? name : ""), raw_inode->ino,
-                 raw_inode->version, total_size));
+                 total_size));
 
        jffs_fm_write_lock(fmc);
 
        while (!fm) {
 
+               /* Deadlocks suck. */
+               while(fmc->free_size < fmc->min_free_size + total_size + slack) {
+                       jffs_fm_write_unlock(fmc);
+                       if (!JFFS_ENOUGH_SPACE(c, total_size + slack))
+                               return -ENOSPC;
+                       jffs_fm_write_lock(fmc);
+               }
+
                /* First try to allocate some flash memory.  */
                err = jffs_fmalloc(fmc, total_size, node, &fm);
                
@@ -1431,6+1510,15 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
 
        pos = node->fm->offset;
 
+       /* Increment the version number here. We can't let the caller
+          set it beforehand, because we might have had to do GC on a node
+          of this file - and we'd end up reusing version numbers.
+       */
+       if (f) {
+               raw_inode->version = f->highest_version + 1;
+               D1(printk (KERN_NOTICE "jffs_write_node(): setting version of %s to %d\n", f->name, raw_inode->version));
+       }
+
        /* Compute the checksum for the data and name chunks.  */
        raw_inode->dchksum = jffs_checksum(data, raw_inode->dsize);
        raw_inode->nchksum = jffs_checksum(name, raw_inode->nsize);
@@ -1496,8+1584,9 @@ jffs_write_node(struct jffs_control *c, struct jffs_node *node,
    shouldn't be read again.  'max_size' is how much space there is in
    the buffer.  */
 static int
-jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, char *buf,
-                  __u32 node_offset, __u32 max_size, kdev_t dev)
+jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, 
+                  unsigned char *buf,__u32 node_offset, __u32 max_size,
+                  kdev_t dev)
 {
        struct jffs_fmcontrol *fmc = f->c->fmc;
        __u32 pos = node->fm->offset + node->fm_offset + node_offset;
@@ -1521,14+1610,15 @@ jffs_get_node_data(struct jffs_file *f, struct jffs_node *node, char *buf,
 /* Read data from the file's nodes.  Write the data to the buffer
    'buf'.  'read_offset' tells how much data we should skip.  */
 int
-jffs_read_data(struct jffs_file *f, char *buf, __u32 read_offset, __u32 size)
+jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset,
+              __u32 size)
 {
        struct jffs_node *node;
        __u32 read_data = 0; /* Total amount of read data.  */
        __u32 node_offset = 0;
        __u32 pos = 0; /* Number of bytes traversed.  */
 
-       D1(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
+       D2(printk("jffs_read_data(): file = \"%s\", read_offset = %d, "
                  "size = %u\n",
                  (f->name ? f->name : ""), read_offset, size));
 
@@ -1842,7+1932,21 @@ jffs_delete_data(struct jffs_file *f, struct jffs_node *node)
                n = n->range_next;
        }
 
-       f->size -= node->removed_size;
+       if (node->removed_size > (f->size - node->data_offset)) {
+               /* It's possible that the removed_size is in fact
+                * greater than the amount of data we actually thought
+                * were present in the first place - some of the nodes 
+                * which this node originally obsoleted may already have
+                * been deleted from the flash by subsequent garbage 
+                * collection.
+                *
+                * If this is the case, don't let f->size go negative.
+                * Bad things would happen :)
+                */
+               f->size = node->data_offset;
+       } else {
+               f->size -= node->removed_size;
+       }
        D3(printk("jffs_delete_data(): f->size = %d\n", f->size));
        return 0;
 } /* jffs_delete_data()  */
@@ -1881,7+1985,7 @@ jffs_insert_data(struct jffs_file *f, struct jffs_node *node)
                /* Find the correct place for the insertion and then insert
                   the node.  */
                for (n = f->range_head; n; n = n->range_next) {
-                       D1(printk("Cool stuff's happening!\n"));
+                       D2(printk("Cool stuff's happening!\n"));
 
                        if (n->data_offset == node->data_offset) {
                                node->range_prev = n->range_prev;
@@ -2223,7+2327,7 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
        int err;
 
        D1(printk("***jffs_rewrite_data(): node: %u, name: \"%s\", size: %u\n",
-                 f->ino, (f->name ? f->name : ""), size));
+                 f->ino, (f->name ? f->name : "(null)"), size));
 
        /* Create and initialize the new node.  */
        if (!(new_node = (struct jffs_node *)
@@ -2235,8+2339,8 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
        DJM(no_jffs_node++);
        new_node->data_offset = node->data_offset;
        new_node->removed_size = size;
-       total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
-       total_data_size = size + JFFS_GET_PAD_BYTES(size);
+       total_name_size = JFFS_PAD(f->nsize);
+       total_data_size = JFFS_PAD(size);
        total_size = sizeof(struct jffs_raw_inode)
                     + total_name_size + total_data_size;
        new_node->fm_offset = sizeof(struct jffs_raw_inode)
@@ -2252,31+2356,24 @@ jffs_rewrite_data(struct jffs_file *f, struct jffs_node *node, int size)
                return err;
        }
        else if (!fm->nodes) {
-               /* The jffs_fm struct that we got is not good enough.  */
+               /* The jffs_fm struct that we got is not big enough.  */
+               /* This should never happen, because we deal with this case
+                  in jffs_garbage_collect_next().*/
+               printk(KERN_WARNING "jffs_rewrite_data(): Allocated node is too small (%d bytes of %d)\n", fm->size, total_size);
                if ((err = jffs_write_dummy_node(c, fm)) < 0) {
-                       DJM(no_jffs_fm--);
-                       jffs_fm_write_unlock(fmc);
                        D(printk("jffs_rewrite_data(): "
                                 "jffs_write_dummy_node() Failed!\n"));
-                       kfree(fm);
-                       return err;
-               }
-               /* Get a new one.  */
-               if ((err = jffs_fmalloc(fmc, total_size, node, &fm)) < 0) {
-                       jffs_fm_write_unlock(fmc);
-                       D(printk("jffs_rewrite_data(): Second "
-                                "jffs_fmalloc(0x%p, %u) failed!\n",
-                                fmc, total_size));
-                       return err;
+               } else {
+                       err = -ENOSPC;
                }
+               DJM(no_jffs_fm--);
+               jffs_fm_write_unlock(fmc);
+               kfree(fm);
+               
+               return err;
        }
        new_node->fm = fm;
 
-       ASSERT(if (new_node->fm->nodes == 0) {
-               printk(KERN_ERR "jffs_rewrite_data(): "
-                      "new_node->fm->nodes == 0\n");
-       });
-
        /* Initialize the raw inode.  */
        raw_inode.magic = JFFS_MAGIC_BITMASK;
        raw_inode.ino = f->ino;
@@ -2418,10+2515,11 @@ jffs_garbage_collect_next(struct jffs_control *c)
        struct jffs_fmcontrol *fmc = c->fmc;
        struct jffs_node *node;
        struct jffs_file *f;
-       int size;
+       int size, err = 0;
        int data_size;
        int total_name_size;
-       int free_size = fmc->flash_size - (fmc->used_size + fmc->dirty_size);
+       __u32 extra_available;
+       __u32 space_needed;
        __u32 free_chunk_size1 = jffs_free_size1(fmc);
        D2(__u32 free_chunk_size2 = jffs_free_size2(fmc));
 
@@ -2430,47+2528,64 @@ jffs_garbage_collect_next(struct jffs_control *c)
        ASSERT(if (!node) {
                printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
                       "No oldest node found!\n");
-               return -1;
+                err = -1;
+                goto jffs_garbage_collect_next_end;
+               
+
        });
 
        /* Find its corresponding file too.  */
        f = jffs_find_file(c, node->ino);
-       ASSERT(if (!f) {
-               printk(KERN_ERR "JFFS: jffs_garbage_collect_next: "
-                      "No file to garbage collect! "
-                      "(ino = 0x%08x)\n", node->ino);
-               return -1;
-       });
+
+       if (!f) {
+         printk (KERN_ERR "JFFS: jffs_garbage_collect_next: "
+                  "No file to garbage collect! "
+                 "(ino = 0x%08x)\n", node->ino);
+          /* FIXME: Free the offending node and recover. */
+          err = -1;
+          goto jffs_garbage_collect_next_end;
+       }
+
+       /* We always write out the name. Theoretically, we don't need
+          to, but for now it's easier - because otherwise we'd have
+          to keep track of how many times the current name exists on
+          the flash and make sure it never reaches zero.
+
+          The current approach means that would be possible to cause
+          the GC to end up eating its tail by writing lots of nodes
+          with no name for it to garbage-collect. Hence the change in
+          inode.c to write names with _every_ node.
+
+          It sucks, but it _should_ work.
+       */
+       total_name_size = JFFS_PAD(f->nsize);
 
        D1(printk("jffs_garbage_collect_next(): \"%s\", "
-                 "ino: %u, version: %u\n",
-                 (f->name ? f->name : ""), node->ino, node->version));
+                 "ino: %u, version: %u, location 0x%x, dsize %u\n",
+                 (f->name ? f->name : ""), node->ino, node->version, 
+                 node->fm->offset, node->data_size));
 
-       /* Compute how much we want to rewrite at the moment.  */
+       /* Compute how many data it's possible to rewrite at the moment.  */
        data_size = f->size - node->data_offset;
-       total_name_size = f->nsize + JFFS_GET_PAD_BYTES(f->nsize);
+
+       /* And from that, the total size of the chunk we want to write */
        size = sizeof(struct jffs_raw_inode) + total_name_size
               + data_size + JFFS_GET_PAD_BYTES(data_size);
 
-       D2(printk("  total_name_size: %u\n", total_name_size));
-       D2(printk("  data_size: %u\n", data_size));
-       D2(printk("  size: %u\n", size));
-       D2(printk("  f->nsize: %u\n", f->nsize));
-       D2(printk("  f->size: %u\n", f->size));
-       D2(printk("  node->data_offset: %u\n", node->data_offset));
-       D2(printk("  free_chunk_size1: %u\n", free_chunk_size1));
-       D2(printk("  free_chunk_size2: %u\n", free_chunk_size2));
-       D2(printk("  node->fm->offset: 0x%08x\n", node->fm->offset));
-
+       /* If that's more than max_chunk_size, reduce it accordingly */
        if (size > fmc->max_chunk_size) {
                size = fmc->max_chunk_size;
                data_size = size - sizeof(struct jffs_raw_inode)
                            - total_name_size;
        }
+
+       /* If we're asking to take up more space than free_chunk_size1
+          but we _could_ fit in it, shrink accordingly.
+       */
        if (size > free_chunk_size1) {
 
                if (free_chunk_size1 <
-                   (sizeof(struct jffs_raw_inode) + f->nsize + BLOCK_SIZE)) {
+                   (sizeof(struct jffs_raw_inode) + total_name_size + BLOCK_SIZE)){
                        /* The space left is too small to be of any
                           use really.  */
                        struct jffs_fm *dirty_fm
@@ -2482,32+2597,81 @@ jffs_garbage_collect_next(struct jffs_control *c)
                                       "jffs_garbage_collect_next: "
                                       "Failed to allocate `dirty' "
                                       "flash memory!\n");
-                               return -1;
+                               err = -1;
+                                goto jffs_garbage_collect_next_end;
                        }
+                       D1(printk("Dirtying end of flash - too small\n"));
                        jffs_write_dummy_node(c, dirty_fm);
+                        err = 0;
                        goto jffs_garbage_collect_next_end;
                }
+               D1(printk("Reducing size of new node from %d to %d to avoid "
+                         " exceeding free_chunk_size1\n",
+                         size, free_chunk_size1));
 
                size = free_chunk_size1;
                data_size = size - sizeof(struct jffs_raw_inode)
                            - total_name_size;
        }
 
-       D2(printk("  size: %u (again)\n", size));
 
-       if (free_size - size < fmc->sector_size) {
-               /* Just rewrite that node (or even less).  */
-               jffs_rewrite_data(f, node,
-                                 jffs_min(node->data_size, data_size));
-       }
-       else {
-               size -= (sizeof(struct jffs_raw_inode) + f->nsize);
-               jffs_rewrite_data(f, node, data_size);
-       }
+       /* Calculate the amount of space needed to hold the nodes
+          which are remaining in the tail */
+       space_needed = fmc->min_free_size - (node->fm->offset % fmc->sector_size);
+
+       /* From that, calculate how much 'extra' space we can use to
+          increase the size of the node we're writing from the size
+          of the node we're obsoleting
+       */
+       if (space_needed > fmc->free_size) {
+               /* If we've gone below min_free_size for some reason,
+                  don't fuck up. This is why we have 
+                  min_free_size > sector_size. Whinge about it though,
+                  just so I can convince myself my maths is right.
+               */
+               D1(printk(KERN_WARNING "jffs_garbage_collect_next(): "
+                         "space_needed %d exceeded free_size %d\n",
+                         space_needed, fmc->free_size));
+               extra_available = 0;
+       } else {
+               extra_available = fmc->free_size - space_needed;
+       }
+
+       /* Check that we don't use up any more 'extra' space than
+          what's available */
+       if (size > JFFS_PAD(node->data_size) + total_name_size + 
+           sizeof(struct jffs_raw_inode) + extra_available) {
+               D1(printk("Reducing size of new node from %d to %ld to avoid "
+                      "catching our tail\n", size, 
+                         JFFS_PAD(node->data_size) + JFFS_PAD(node->name_size) + 
+                         sizeof(struct jffs_raw_inode) + extra_available));
+               D1(printk("space_needed = %d, extra_available = %d\n", 
+                         space_needed, extra_available));
+
+               size = JFFS_PAD(node->data_size) + total_name_size + 
+                 sizeof(struct jffs_raw_inode) + extra_available;
+               data_size = size - sizeof(struct jffs_raw_inode)
+                       - total_name_size;
+       };
 
+       D2(printk("  total_name_size: %u\n", total_name_size));
+       D2(printk("  data_size: %u\n", data_size));
+       D2(printk("  size: %u\n", size));
+       D2(printk("  f->nsize: %u\n", f->nsize));
+       D2(printk("  f->size: %u\n", f->size));
+       D2(printk("  node->data_offset: %u\n", node->data_offset));
+       D2(printk("  free_chunk_size1: %u\n", free_chunk_size1));
+       D2(printk("  free_chunk_size2: %u\n", free_chunk_size2));
+       D2(printk("  node->fm->offset: 0x%08x\n", node->fm->offset));
+
+       if ((err = jffs_rewrite_data(f, node, data_size))) {
+               printk(KERN_WARNING "jffs_rewrite_data() failed: %d\n", err);
+               return err;
+       }
+         
 jffs_garbage_collect_next_end:
        D3(printk("jffs_garbage_collect_next: Leaving...\n"));
-       return 0;
+       return err;
 } /* jffs_garbage_collect_next */
 
 
@@ -2683,75+2847,75 @@ jffs_try_to_erase(struct jffs_control *c)
    for exemple).  Of course there is a limit on how intelligent this garbage
    collection can be.  */
 
+
 int
 jffs_garbage_collect_now(struct jffs_control *c)
 {
        struct jffs_fmcontrol *fmc = c->fmc;
-       long erased_total = 0;
-       long erased;
+       long erased = 0;
        int result = 0;
        D1(int i = 1);
-       D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u\n",
-                 fmc->dirty_size));
+       D2(printk("***jffs_garbage_collect_now(): fmc->dirty_size = %u, fmc->free_size = 0x%x\n, fcs1=0x%x, fcs2=0x%x",
+                 fmc->dirty_size, fmc->free_size, jffs_free_size1(fmc), jffs_free_size2(fmc)));
        D2(jffs_print_fmcontrol(fmc));
 
-       down(&fmc->gclock);
+       //      down(&fmc->gclock);
 
        /* If it is possible to garbage collect, do so.  */
-
-       if (fmc->dirty_size >= fmc->sector_size) {
-
+       
+       while (erased == 0) {
                D1(printk("***jffs_garbage_collect_now(): round #%u, "
-                        "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
+                         "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
                D2(jffs_print_fmcontrol(fmc));
 
-               /* At least one sector should be able to free now.  */
                if ((erased = jffs_try_to_erase(c)) < 0) {
                        printk(KERN_WARNING "JFFS: Error in "
                               "garbage collector.\n");
                        result = erased;
                        goto gc_end;
                }
-               else if (erased == 0) {
-                       __u32 free_size = fmc->flash_size
-                                         - (fmc->used_size
-                                            + fmc->dirty_size);
-
-                       if (free_size > 0) {
-                               /* Let's dare to make a garbage collect.  */
-                               if ((result = jffs_garbage_collect_next(c))
-                                   < 0) {
-                                       printk(KERN_ERR "JFFS: Something "
-                                              "has gone seriously wrong "
-                                              "with a garbage collect.\n");
-                                       goto gc_end;
-                               }
-                       }
-                       else {
-                               /* What should we do here?  */
-                               D(printk("   jffs_garbage_collect_now(): "
-                                        "erased: %ld, free_size: %u\n",
-                                        erased, free_size));
-                               result = -1;
-                               goto gc_end;
-                       }
+               if (erased)
+                       break;
+               
+               if (fmc->free_size == 0) {
+                       /* Argh */
+                       printk(KERN_ERR "jffs_garbage_collect_now(): free_size == 0. This is BAD.\n");
+                       result = -ENOSPC;
+                       break;
+               }
+
+               if (fmc->dirty_size < fmc->sector_size) {
+                       /* Actually, we _may_ have been able to free some, 
+                        * if there are many overlapping nodes which aren't
+                        * actually marked dirty because they still have
+                        * some valid data in each.
+                        */
+                       result = -ENOSPC;
+                       break;
+               }
+
+               /* Let's dare to make a garbage collect.  */
+               if ((result = jffs_garbage_collect_next(c)) < 0) {
+                       printk(KERN_ERR "JFFS: Something "
+                              "has gone seriously wrong "
+                              "with a garbage collect.\n");
+                       goto gc_end;
                }
 
                D1(printk("   jffs_garbage_collect_now(): erased: %ld\n", erased));
-               erased_total += erased;
                DJM(jffs_print_memory_allocation_statistics());
        }
-
+       
 gc_end:
-       up(&fmc->gclock);
+       //      up(&fmc->gclock);
 
        D3(printk("   jffs_garbage_collect_now(): Leaving...\n"));
-       D1(if (erased_total) {
-               printk("erased_total = %ld\n", erased_total);
+       D1(if (erased) {
+               printk("jffs_g_c_now(): erased = %ld\n", erased);
                jffs_print_fmcontrol(fmc);
        });
 
-       if (!erased_total && !result)
+       if (!erased && !result)
                return -ENOSPC;
 
        return result;
@@ -2766,17+2930,15 @@ gc_end:
 */
 static inline int thread_should_wake (struct jffs_control *c)
 {
-       __u32 nfree = c->fmc->flash_size - c->fmc->used_size - c->fmc->dirty_size;
-
        D1(printk (KERN_NOTICE "thread_should_wake(): free=%d, dirty=%d, blocksize=%d.\n",
-                  nfree, c->fmc->dirty_size, c->fmc->sector_size));
+                  c->fmc->free_size, c->fmc->dirty_size, c->fmc->sector_size));
 
        /* If there's not enough dirty space to free a block, there's no point. */
        if (c->fmc->dirty_size < c->fmc->sector_size)
                return 0;
 
        /* If there are fewer free bytes than the threshold, GC */
-       if (nfree < c->gc_minfree_threshold)
+       if (c->fmc->dirty_size < c->gc_minfree_threshold)
                return 1;
 
        /* If there are more dirty bytes than the threshold, GC */
@@ -2807,7+2969,6 @@ jffs_garbage_collect_thread(void *ptr)
 {
         struct jffs_control *c = (struct jffs_control *) ptr;
        struct jffs_fmcontrol *fmc = c->fmc;
-       long erased_total = 0;
        long erased;
        int result = 0;
        D1(int i = 1);
@@ -2821,7+2982,7 @@ jffs_garbage_collect_thread(void *ptr)
        current->pgrp = 1;
        init_MUTEX_LOCKED(&c->gc_thread_sem); /* barrier */ 
        spin_lock_irq(&current->sigmask_lock);
-       siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGQUIT) | sigmask(SIGSTOP) | sigmask(SIGCONT));
+       siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
        recalc_sigpending(current);
        spin_unlock_irq(&current->sigmask_lock);
        strcpy(current->comm, "jffs_gcd");
@@ -2829,6+2990,7 @@ jffs_garbage_collect_thread(void *ptr)
        D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): Starting infinite loop.\n"));
 
        for (;;) {
+
                /* See if we need to start gc.  If we don't, go to sleep.
                   
                   Current implementation is a BAD THING(tm).  If we try 
@@ -2836,7+2998,7 @@ jffs_garbage_collect_thread(void *ptr)
                   for this thread to exit.  We need to arrange to send it a
                   sig before the umount process sleeps.
                */
-               
+
                if (!thread_should_wake(c))
                        set_current_state (TASK_INTERRUPTIBLE);
                
@@ -2844,7+3006,7 @@ jffs_garbage_collect_thread(void *ptr)
                                       on immediately - we're a low priority 
                                       background task. */
 
-               /* Put_super will send a SIGQUIT and then wait on the sem. 
+               /* Put_super will send a SIGKILL and then wait on the sem. 
                 */
                while (signal_pending(current)) {
                        siginfo_t info;
@@ -2861,8+3023,8 @@ jffs_garbage_collect_thread(void *ptr)
                                schedule();
                                break;
 
-                       case SIGQUIT:
-                               D1(printk("jffs_garbage_collect_thread(): SIGQUIT received.\n"));
+                       case SIGKILL:
+                               D1(printk("jffs_garbage_collect_thread(): SIGKILL received.\n"));
                                c->gc_task = NULL;
                                up(&c->gc_thread_sem);
                                unlock_kernel();
@@ -2872,69+3034,44 @@ jffs_garbage_collect_thread(void *ptr)
 
 
                D1(printk (KERN_NOTICE "jffs_garbage_collect_thread(): collecting.\n"));
-//             printk (KERN_NOTICE "free=%d, dirty=%d, blocksize=%ld.\n", count_free_bytes(c), count_dirty_bytes(c), c->sb->s_blocksize);
 
-               D2(printk("***jffs_garbage_collect_thread(): fmc->dirty_size = %u\n",
-                         fmc->dirty_size));
-               D2(jffs_print_fmcontrol(fmc));
-               
                if (fmc->dirty_size < fmc->sector_size) {
-                       printk(KERN_WARNING "jffs_garbage_collect_thread with insufficient dirty space (0x%x)\n", fmc->dirty_size);
+                       D1(printk(KERN_WARNING "jffs_garbage_collect_thread with insufficient dirty space (0x%x)\n", fmc->dirty_size));
                        continue;
                }
 
-               down(&c->fmc->gclock);
-                       
+               D3(printk (KERN_NOTICE "g_c_thread(): down biglock\n"));
+               down(&fmc->biglock);
+               
                D1(printk("***jffs_garbage_collect_thread(): round #%u, "
                          "fmc->dirty_size = %u\n", i++, fmc->dirty_size));
                D2(jffs_print_fmcontrol(fmc));
-               
-               /* At least one sector should be able to free now.  */
+
                if ((erased = jffs_try_to_erase(c)) < 0) {
                        printk(KERN_WARNING "JFFS: Error in "
-                              "garbage collector.\n");
-                       result = erased;
+                              "garbage collector: %ld.\n", erased);
+               }
+
+               if (erased)
+                       goto gc_end;
+
+               if (fmc->free_size == 0) {
+                       /* Argh. Might as well commit suicide. */
+                       printk(KERN_ERR "jffs_garbage_collect_thread(): free_size == 0. This is BAD.\n");
+                       send_sig(SIGQUIT, c->gc_task, 1);
+                       // panic()
                        goto gc_end;
                }
-               else if (erased == 0) {
-                       __u32 free_size = fmc->flash_size
-                               - (fmc->used_size
-                                  + fmc->dirty_size);
-                       
-                       if (free_size > 0) {
-                               /* Let's dare to make a garbage collect.  */
-                               if ((result = jffs_garbage_collect_next(c))
-                                   < 0) {
-                                       printk(KERN_ERR "JFFS: Something "
-                                              "has gone seriously wrong "
-                                              "with a garbage collect.\n");
-                                       goto gc_end;
-                               }
-                       }
-                       else {
-                               /* What should we do here?  */
-                               D(printk("   jffs_garbage_collect(): "
-                                        "erased: %ld, free_size: %u\n",
-                                        erased, free_size));
-                               result = -1;
-                               goto gc_end;
-                       }
+               
+               /* Let's dare to make a garbage collect.  */
+               if ((result = jffs_garbage_collect_next(c)) < 0) {
+                       printk(KERN_ERR "JFFS: Something "
+                              "has gone seriously wrong "
+                              "with a garbage collect: %d\n", result);
                }
-
-               D1(printk("   jffs_garbage_collect(): erased: %ld\n", erased));
-               erased_total += erased;
-               DJM(jffs_print_memory_allocation_statistics());
-       
                
        gc_end:
-               up(&c->fmc->gclock);
-               
-               D3(printk("   jffs_garbage_collect(): Leaving...\n"));
-               D1(if (erased_total) {
-                       printk("erased_total = %ld\n", erased_total);
-                       jffs_print_fmcontrol(fmc);
-               });
-       
+               D3(printk (KERN_NOTICE "g_c_thread(): up biglock\n"));
+               up(&fmc->biglock);
        } /* for (;;) */
 } /* jffs_garbage_collect_thread() */
-
index d4638af..f10a994 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: intrep.h,v 1.6 2000/08/04 14:29:17 dwmw2 Exp $
+ * $Id: intrep.h,v 1.11 2000/08/17 22:46:46 bmatthews Exp $
  *
  */
 
@@ -46,8+46,9 @@ int jffs_file_count(struct jffs_file *f);
 
 int jffs_write_node(struct jffs_control *c, struct jffs_node *node,
                    struct jffs_raw_inode *raw_inode,
-                   const char *name, const unsigned char *buf);
-int jffs_read_data(struct jffs_file *f, char *buf, __u32 read_offset, __u32 size);
+                   const char *name, const unsigned char *buf,
+                   int recoverable, struct jffs_file *f);
+int jffs_read_data(struct jffs_file *f, unsigned char *buf, __u32 read_offset, __u32 size);
 
 /* Garbage collection stuff.  */
 int jffs_garbage_collect_thread(void *c);
@@ -55,19+56,22 @@ void jffs_garbage_collect_trigger(struct jffs_control *c);
 int jffs_garbage_collect_now(struct jffs_control *c);
 
 /* Is there enough space on the flash?  */
-static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c)
+static inline int JFFS_ENOUGH_SPACE(struct jffs_control *c, __u32 space)
 {
        struct jffs_fmcontrol *fmc = c->fmc;
 
        while (1) {
                if ((fmc->flash_size - (fmc->used_size + fmc->dirty_size)) 
-                       >= fmc->min_free_size) {
+                       >= fmc->min_free_size + space) {
                        return 1;
                }
                if (fmc->dirty_size < fmc->sector_size)
                        return 0;
 
-               jffs_garbage_collect_now(c);
+               if (jffs_garbage_collect_now(c)) {
+                 D1(printk("JFFS_ENOUGH_SPACE: jffs_garbage_collect_now() failed.\n"));
+                 return 0;
+               }
        }
 }
 
index 3140b8a..b9bbeb4 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: jffs_fm.c,v 1.14 2000/08/09 14:26:35 dwmw2 Exp $
+ * $Id: jffs_fm.c,v 1.18 2000/08/21 10:41:45 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
@@ -57,17+57,26 @@ jffs_build_begin(struct jffs_control *c, kdev_t dev)
 
        fmc->used_size = 0;
        fmc->dirty_size = 0;
+       fmc->free_size = mtd->size;
        fmc->sector_size = mtd->erasesize;
        fmc->max_chunk_size = fmc->sector_size >> 1;
-       fmc->min_free_size = (fmc->sector_size << 1) - fmc->max_chunk_size;
+       /* min_free_size:
+          1 sector, obviously.
+          + 1 x max_chunk_size, for when a nodes overlaps the end of a sector
+          + 1 x max_chunk_size again, which ought to be enough to handle 
+                  the case where a rename causes a name to grow, and GC has
+                  to write out larger nodes than the ones it's obsoleting.
+                  We should fix it so it doesn't have to write the name
+                  _every_ time. Later.
+       */
+       fmc->min_free_size = fmc->sector_size << 1;
        fmc->mtd = mtd;
-       init_MUTEX(&fmc->gclock);
        fmc->c = c;
        fmc->head = 0;
        fmc->tail = 0;
        fmc->head_extra = 0;
        fmc->tail_extra = 0;
-       init_MUTEX(&fmc->wlock);
+       init_MUTEX(&fmc->biglock);
        return fmc;
 }
 
@@ -203,6+212,11 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
 
        free_chunk_size1 = jffs_free_size1(fmc);
        free_chunk_size2 = jffs_free_size2(fmc);
+       if (free_chunk_size1 + free_chunk_size2 != fmc->free_size) {
+               printk(KERN_WARNING "Free size accounting screwed\n");
+               printk(KERN_WARNING "free_chunk_size1 == 0x%x, free_chunk_size2 == 0x%x, fmc->free_size == 0x%x\n", free_chunk_size1, free_chunk_size2, fmc->free_size);
+       }
+
        D3(printk("jffs_fmalloc(): free_chunk_size1 = %u, "
                  "free_chunk_size2 = %u\n",
                  free_chunk_size1, free_chunk_size2));
@@ -240,6+254,7 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
                        fm->offset = fmc->flash_start;
                }
                fm->size = size;
+               fmc->free_size -= size;
                fmc->used_size += size;
        }
        else if (size > free_chunk_size2) {
@@ -253,6+268,7 @@ jffs_fmalloc(struct jffs_fmcontrol *fmc, __u32 size, struct jffs_node *node,
                fm->offset = fmc->tail->offset + fmc->tail->size;
                fm->size = free_chunk_size1;
                fm->nodes = 0;
+               fmc->free_size -= fm->size;
                fmc->dirty_size += fm->size; /* Changed by simonk. This seemingly fixes a 
                                                bug that caused infinite garbage collection.
                                                It previously set fmc->dirty_size to size (which is the
@@ -380,10+396,12 @@ jffs_fmalloced(struct jffs_fmcontrol *fmc, __u32 offset, __u32 size,
                fm->nodes->node = node;
                fm->nodes->next = 0;
                fmc->used_size += size;
+               fmc->free_size -= size;
        }
        else {
                /* If there is no node, then this is just a chunk of dirt.  */
                fmc->dirty_size += size;
+               fmc->free_size -= size;
        }
 
        if (fmc->head_extra) {
@@ -505,6+523,7 @@ jffs_sync_erase(struct jffs_fmcontrol *fmc, int erased_size)
        });
 
        fmc->dirty_size -= erased_size;
+       fmc->free_size += erased_size;
 
        for (fm = fmc->head; fm && (erased_size > 0);) {
                if (erased_size >= fm->size) {
@@ -701,6+720,7 @@ jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
        D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
        D(printk("        %u, /* used_size  */\n", fmc->used_size));
        D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
+       D(printk("        %u, /* free_size  */\n", fmc->free_size));
        D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
        D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
        D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
index 82077d9..2bac0cb 100644 (file)
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- * $Id: jffs_fm.h,v 1.7 2000/08/08 09:10:39 dwmw2 Exp $
+ * $Id: jffs_fm.h,v 1.10 2000/08/17 15:42:44 dwmw2 Exp $
  *
  * Ported to Linux 2.3.x and MTD:
  * Copyright (C) 2000  Alexander Larsson (alex@cendio.se), Cendio Systems AB
 #define JFFS_GET_PAD_BYTES(size) ((JFFS_ALIGN_SIZE                     \
                                  - ((__u32)(size) % JFFS_ALIGN_SIZE)) \
                                  % JFFS_ALIGN_SIZE)
-
+#define JFFS_PAD(size) ( (size + (JFFS_ALIGN_SIZE-1)) & ~(JFFS_ALIGN_SIZE-1) )
 struct jffs_node_ref
 {
        struct jffs_node *node;
@@ -86,18+86,18 @@ struct jffs_fmcontrol
        __u32 flash_size;
        __u32 used_size;
        __u32 dirty_size;
+       __u32 free_size;
        __u32 sector_size;
        __u32 min_free_size;  /* The minimum free space needed to be able
                                 to perform garbage collections.  */
        __u32 max_chunk_size; /* The maximum size of a chunk of data.  */
        struct mtd_info *mtd;
-       struct semaphore gclock;
        struct jffs_control *c;
        struct jffs_fm *head;
        struct jffs_fm *tail;
        struct jffs_fm *head_extra;
        struct jffs_fm *tail_extra;
-       struct semaphore wlock;  
+       struct semaphore biglock;
 };
 
 /* Notice the two members head_extra and tail_extra in the jffs_control
index 1c0f13e..eda3fe6 100644 (file)
@@ -342,7+342,8 @@ ncp_d_validate(struct dentry *dentry)
                goto bad_addr;
        if ((dent_addr & ~align_mask) != dent_addr)
                goto bad_align;
-       if (!kern_addr_valid(dent_addr))
+       if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 +
+                                               sizeof(struct dentry))))
                goto bad_addr;
        /*
         * Looks safe enough to dereference ...
index fe944ba..00c1676 100644 (file)
@@ -4,8+4,9 @@
  *     Modelled on fs/exec.c:aout_core_dump()
  *     Jeremy Fitzhardinge <jeremy@sw.oz.au>
  *     ELF version written by David Howells <David.Howells@nexor.co.uk>
- *     Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@sco.com>
- *     Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@sco.com>
+ *     Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@veritas.com>
+ *     Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@veritas.com>
+ *     Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar <kanoj@sgi.com>
  */
 
 #include <linux/config.h>
@@ -112,18+113,17 @@ extern char saved_command_line[];
 
 static size_t get_kcore_size(int *num_vma, size_t *elf_buflen)
 {
-       size_t try, size = 0;
+       size_t try, size;
        struct vm_struct *m;
 
        *num_vma = 0;
+       size = ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
        if (!vmlist) {
                *elf_buflen = PAGE_SIZE;
-               return ((size_t)high_memory - PAGE_OFFSET + PAGE_SIZE);
+               return (size);
        }
 
        for (m=vmlist; m; m=m->next) {
-               if (m->flags & VM_IOREMAP) /* don't dump ioremap'd stuff! (TA) */
-                       continue;
                try = (size_t)m->addr + m->size;
                if (try > size)
                        size = try;
@@ -315,6+315,7 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
        size_t size, tsz;
        size_t elf_buflen;
        int num_vma;
+       unsigned long start;
 
        read_lock(&vmlist_lock);
        proc_root_kcore->size = size = get_kcore_size(&num_vma, &elf_buflen);
@@ -380,11+381,77 @@ static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t
        }
 #endif
        /* fill the remainder of the buffer from kernel VM space */
-       if (copy_to_user(buffer, __va(*fpos - elf_buflen), buflen))
-               return -EFAULT;
+       start = (unsigned long)__va(*fpos - elf_buflen);
+       if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
+               tsz = buflen;
+               
+       while (buflen) {
+               if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
+                       char * elf_buf;
+                       struct vm_struct *m;
+                       unsigned long curstart = start;
+                       unsigned long cursize = tsz;
+
+                       elf_buf = kmalloc(tsz, GFP_KERNEL);
+                       if (!elf_buf)
+                               return -ENOMEM;
+                       memset(elf_buf, 0, tsz);
+
+                       read_lock(&vmlist_lock);
+                       for (m=vmlist; m && cursize; m=m->next) {
+                               unsigned long vmstart;
+                               unsigned long vmsize;
+                               unsigned long msize = m->size - PAGE_SIZE;
+
+                               if (((unsigned long)m->addr + msize) < 
+                                                               curstart)
+                                       continue;
+                               if ((unsigned long)m->addr > (curstart + 
+                                                               cursize))
+                                       break;
+                               vmstart = (curstart < (unsigned long)m->addr ? 
+                                       (unsigned long)m->addr : curstart);
+                               if (((unsigned long)m->addr + msize) > 
+                                                       (curstart + cursize))
+                                       vmsize = curstart + cursize - vmstart;
+                               else
+                                       vmsize = (unsigned long)m->addr + 
+                                                       msize - vmstart;
+                               curstart = vmstart + vmsize;
+                               cursize -= vmsize;
+                               /* don't dump ioremap'd stuff! (TA) */
+                               if (m->flags & VM_IOREMAP)
+                                       continue;
+                               memcpy(elf_buf + (vmstart - start),
+                                       (char *)vmstart, vmsize);
+                       }
+                       read_unlock(&vmlist_lock);
+                       if (copy_to_user(buffer, elf_buf, tsz)) {
+                               kfree(elf_buf);
+                               return -EFAULT;
+                       }
+                       kfree(elf_buf);
+               } else if ((start > PAGE_OFFSET) && (start < 
+                                               (unsigned long)high_memory)) {
+                       if (kern_addr_valid(start)) {
+                               if (copy_to_user(buffer, (char *)start, tsz))
+                                       return -EFAULT;
+                       } else {
+                               if (clear_user(buffer, tsz))
+                                       return -EFAULT;
+                       }
+               } else {
+                       if (clear_user(buffer, tsz))
+                               return -EFAULT;
+               }
+               buflen -= tsz;
+               *fpos += tsz;
+               buffer += tsz;
+               acc += tsz;
+               start += tsz;
+               tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen);
+       }
 
-       acc += buflen;
-       *fpos += buflen;
        return acc;
 }
 #endif /* CONFIG_KCORE_AOUT */
index 2956def..c856efe 100644 (file)
@@ -79,6+79,7 @@ struct mpc_config_bus
        unsigned char mpc_bustype[6] __attribute((packed));
 };
 
+/* List of Bus Type string values, Intel MP Spec. */
 #define BUSTYPE_EISA   "EISA"
 #define BUSTYPE_ISA    "ISA"
 #define BUSTYPE_INTERN "INTERN"        /* Internal BUS */
@@ -86,6+87,17 @@ struct mpc_config_bus
 #define BUSTYPE_VL     "VL"            /* Local bus */
 #define BUSTYPE_PCI    "PCI"
 #define BUSTYPE_PCMCIA "PCMCIA"
+#define BUSTYPE_CBUS   "CBUS"
+#define BUSTYPE_CBUSII "CBUSII"
+#define BUSTYPE_FUTURE "FUTURE"
+#define BUSTYPE_MBI    "MBI"
+#define BUSTYPE_MBII   "MBII"
+#define BUSTYPE_MPI    "MPI"
+#define BUSTYPE_MPSA   "MPSA"
+#define BUSTYPE_NUBUS  "NUBUS"
+#define BUSTYPE_TC     "TC"
+#define BUSTYPE_VME    "VME"
+#define BUSTYPE_XPRESS "XPRESS"
 
 struct mpc_config_ioapic
 {
@@ -147,7+159,7 @@ struct mpc_config_lintsrc
 #define MAX_IRQ_SOURCES 128
 #define MAX_MP_BUSSES 32
 enum mp_bustype {
-       MP_BUS_ISA,
+       MP_BUS_ISA = 1,
        MP_BUS_EISA,
        MP_BUS_PCI,
        MP_BUS_MCA
index 5d5b67a..a67aaf4 100644 (file)
@@ -71,7+71,8 @@ static inline int spin_trylock(spinlock_t *lock)
        __asm__ __volatile__(
                "xchgb %b0,%1"
                :"=q" (oldval), "=m" (__dummy_lock(lock))
-               :"0" (0));
+               :"0" (0)
+               :"memory");
        return oldval > 0;
 }
 
@@ -87,7+88,8 @@ printk("eip: %p\n", &&here);
 #endif
        __asm__ __volatile__(
                spin_lock_string
-               :"=m" (__dummy_lock(lock)));
+               :"=m" (__dummy_lock(lock))
+               : :"memory");
 }
 
 extern inline void spin_unlock(spinlock_t *lock)
@@ -100,7+102,8 @@ extern inline void spin_unlock(spinlock_t *lock)
 #endif
        __asm__ __volatile__(
                spin_unlock_string
-               :"=m" (__dummy_lock(lock)));
+               :"=m" (__dummy_lock(lock))
+               : :"memory");
 }
 
 /*
index dc29a13..9e7f4a5 100644 (file)
@@ -18,8+18,6 @@ typedef struct { int counter; } atomic_t;
 #endif
 
 #ifdef __KERNEL__
-#include <asm/system.h>
-#include <asm/psr.h>
 
 #ifndef CONFIG_SMP
 
index fc54589..ed50485 100644 (file)
@@ -431,6+431,7 @@ extern void sparcaudio_input_done(struct sparcaudio_driver *, int);
 extern int sparcaudio_init(void);
 extern int amd7930_init(void);
 extern int cs4231_init(void);
+extern int dbri_init(void);
 
 #endif
 
index 0c54061..5a84229 100644 (file)
 #undef request_region
 #define release_region(X, Y)   do { } while(0)
 #define check_region(X, Y)     (0)
-#define request_region(X, Y, Z)        do { } while(0)
+#define request_region(X, Y, Z)        (1)
 
 /* References:
  * 1) Netbsd Sun floppy driver.
index f650416..5f70403 100644 (file)
@@ -93,12+93,6 @@ extern __inline__ void xc5(smpfunc_t func, unsigned long arg1, unsigned long arg
                           unsigned long arg3, unsigned long arg4, unsigned long arg5)
 { smp_cross_call(func, arg1, arg2, arg3, arg4, arg5); }
 
-extern __inline__ int smp_call_function(void (*func)(void *info), void *info, int nonatomic, int wait)
-{
-       xc1((smpfunc_t)func, (unsigned long)info);
-       return 0;
-}
-
 extern __volatile__ int __cpu_number_map[NR_CPUS];
 extern __volatile__ int __cpu_logical_map[NR_CPUS];
 extern unsigned long smp_proc_in_lock[NR_CPUS];
index bac6318..d46799b 100644 (file)
@@ -376,7+376,7 @@ extern int pgt_cache_water[2];
 extern int check_pgt_cache(void);
 
 extern void free_area_init(unsigned long * zones_size);
-extern void free_area_init_node(int nid, pg_data_t *pgdat, 
+extern void free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
        unsigned long * zones_size, unsigned long zone_start_paddr, 
        unsigned long *zholes_size);
 extern void mem_init(void);
index 61f672a..5c31844 100644 (file)
@@ -99,9+99,11 @@ extern pg_data_t *pgdat_list;
  * The following two are not meant for general usage. They are here as
  * prototypes for the discontig memory code.
  */
+struct page;
 extern void show_free_areas_core(int);
 extern void free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
-  unsigned long *zones_size, unsigned long paddr, unsigned long *zholes_size);
+  unsigned long *zones_size, unsigned long paddr, unsigned long *zholes_size,
+  struct page *pmap);
 
 #ifndef CONFIG_DISCONTIGMEM
 
index ebe8428..95c0e13 100644 (file)
@@ -416,7+416,6 @@ extern int          dev_alloc_name(struct net_device *dev, const char *name);
 extern int             dev_open(struct net_device *dev);
 extern int             dev_close(struct net_device *dev);
 extern int             dev_queue_xmit(struct sk_buff *skb);
-extern void            dev_loopback_xmit(struct sk_buff *skb);
 extern int             register_netdevice(struct net_device *dev);
 extern int             unregister_netdevice(struct net_device *dev);
 extern int             register_netdevice_notifier(struct notifier_block *nb);
index 33e2ee2..cf20a8b 100644 (file)
 
 #ifdef CONFIG_SMP
 
+#include <linux/kernel.h>
 #include <asm/smp.h>
 
 /*
index 20536ca..650d1f0 100644 (file)
@@ -94,12+94,13 @@ struct ip_rt_acct
 
 extern struct ip_rt_acct *ip_rt_acct;
 
+struct in_device;
 extern void            ip_rt_init(void);
 extern void            ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw,
                                       u32 src, u8 tos, struct net_device *dev);
 extern void            ip_rt_advice(struct rtable **rp, int advice);
 extern void            rt_cache_flush(int how);
-extern int             ip_route_output(struct rtable **, u32 dst, u32 src, u32 tos, int oif);
+extern int             ip_route_output_key(struct rtable **, const struct rt_key *key);
 extern int             ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin);
 extern unsigned short  ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu);
 extern void            ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu);
@@ -111,6+112,15 @@ extern int         ip_rt_ioctl(unsigned int cmd, void *arg);
 extern void            ip_rt_get_source(u8 *src, struct rtable *rt);
 extern int             ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb);
 
+/* Deprecated: use ip_route_output_key directly */
+extern __inline__ int ip_route_output(struct rtable **rp,
+                                     u32 daddr, u32 saddr, u32 tos, int oif)
+{
+       struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos };
+
+       return ip_route_output_key(rp, &key);
+}
+
 
 extern __inline__ void ip_rt_put(struct rtable * rt)
 {
index 87f37c3..458a20a 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1201,6+1201,7 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
        int acc_mode;
        struct dentry *dentry;
        char   name[SHM_FMT_LEN+1];
+       void *user_addr;
 
        if (!shm_sb || (shmid % SEQ_MULTIPLIER) == zero_id)
                return -EINVAL;
@@ -1254,13+1255,12 @@ asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)
        if (IS_ERR (file))
                goto bad_file1;
        down(&current->mm->mmap_sem);
-       *raddr = do_mmap (file, addr, file->f_dentry->d_inode->i_size,
-                         prot, flags, 0);
+       user_addr = (void *) do_mmap (file, addr, file->f_dentry->d_inode->i_size, prot, flags, 0);
        up(&current->mm->mmap_sem);
-       if (IS_ERR(*raddr))
-               err = PTR_ERR(*raddr);
-       else
-               err = 0;
+       *raddr = (unsigned long) user_addr;
+       err = 0;
+       if (IS_ERR(user_addr))
+               err = PTR_ERR(user_addr);
        fput (file);
        return err;
 
index 9ab02a4..1d5bbe5 100644 (file)
@@ -44,8+44,12 @@ repeat:
        if (write && (!pte_write(*pgtable) || !pte_dirty(*pgtable)))
                goto fault_in_page;
        page = pte_page(*pgtable);
-       if ((!VALID_PAGE(page)) || PageReserved(page))
-               return 0;
+
+       /* ZERO_PAGE is special: reads from it are ok even though it's marked reserved */
+       if (page != ZERO_PAGE(addr) || write) {
+               if ((!VALID_PAGE(page)) || PageReserved(page))
+                       return 0;
+       }
        flush_cache_page(vma, addr);
 
        if (write) {
index 750421a..9c59e3d 100644 (file)
@@ -146,9+146,40 @@ void invalidate_inode_pages(struct inode * inode)
        spin_unlock(&pagecache_lock);
 }
 
-/*
+static inline void truncate_partial_page(struct page *page, unsigned partial)
+{
+       memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
+                               
+       if (page->buffers)
+               block_flushpage(page, partial);
+
+}
+
+static inline void truncate_complete_page(struct page *page)
+{
+       if (!page->buffers || block_flushpage(page, 0))
+               lru_cache_del(page);
+
+       /*
+        * We remove the page from the page cache _after_ we have
+        * destroyed all buffer-cache references to it. Otherwise some
+        * other process might think this inode page is not in the
+        * page cache and creates a buffer-cache alias to it causing
+        * all sorts of fun problems ...  
+        */
+       ClearPageDirty(page);
+       remove_inode_page(page);
+       page_cache_release(page);
+}
+
+/**
+ * truncate_inode_pages - truncate *all* the pages from an offset
+ * @mapping: mapping to truncate
+ * @lstart: offset from with to truncate
+ *
  * Truncate the page cache at a set offset, removing the pages
  * that are beyond that offset (and zeroing out partial pages).
+ * If any page is locked we wait for it to become unlocked.
  */
 void truncate_inode_pages(struct address_space * mapping, loff_t lstart)
 {
@@ -168,11+199,10 @@ repeat:
 
                page = list_entry(curr, struct page, list);
                curr = curr->next;
-
                offset = page->index;
 
-               /* page wholly truncated - free it */
-               if (offset >= start) {
+               /* Is one of the pages to truncate? */
+               if ((offset >= start) || (partial && (offset + 1) == start)) {
                        if (TryLockPage(page)) {
                                page_cache_get(page);
                                spin_unlock(&pagecache_lock);
@@ -183,23+213,14 @@ repeat:
                        page_cache_get(page);
                        spin_unlock(&pagecache_lock);
 
-                       if (!page->buffers || block_flushpage(page, 0))
-                               lru_cache_del(page);
-
-                       /*
-                        * We remove the page from the page cache
-                        * _after_ we have destroyed all buffer-cache
-                        * references to it. Otherwise some other process
-                        * might think this inode page is not in the
-                        * page cache and creates a buffer-cache alias
-                        * to it causing all sorts of fun problems ...
-                        */
-                       remove_inode_page(page);
-                       ClearPageDirty(page);
+                       if (partial && (offset + 1) == start) {
+                               truncate_partial_page(page, partial);
+                               partial = 0;
+                       } else 
+                               truncate_complete_page(page);
 
                        UnlockPage(page);
                        page_cache_release(page);
-                       page_cache_release(page);
 
                        /*
                         * We have done things without the pagecache lock,
@@ -210,37+231,6 @@ repeat:
                         */
                        goto repeat;
                }
-               /*
-                * there is only one partial page possible.
-                */
-               if (!partial)
-                       continue;
-
-               /* and it's the one preceeding the first wholly truncated page */
-               if ((offset + 1) != start)
-                       continue;
-
-               /* partial truncate, clear end of page */
-               if (TryLockPage(page)) {
-                       spin_unlock(&pagecache_lock);
-                       goto repeat;
-               }
-               page_cache_get(page);
-               spin_unlock(&pagecache_lock);
-
-               memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial);
-               if (page->buffers)
-                       block_flushpage(page, partial);
-
-               partial = 0;
-
-               /*
-                * we have dropped the spinlock so we have to
-                * restart.
-                */
-               UnlockPage(page);
-               page_cache_release(page);
-               goto repeat;
        }
        spin_unlock(&pagecache_lock);
 }
index bbe9ec6..06ad9ec 100644 (file)
--- a/mm/numa.c
+++ b/mm/numa.c
@@ -21,12+21,12 @@ pg_data_t contig_page_data = { bdata: &contig_bootmem_data };
  * at a considerably higher value than 0. Examples are Super-H, ARM, m68k.
  * Should be invoked with paramters (0, 0, unsigned long *[], start_paddr).
  */
-void __init free_area_init_node(int nid, pg_data_t *pgdat, 
+void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
        unsigned long *zones_size, unsigned long zone_start_paddr, 
        unsigned long *zholes_size)
 {
        free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 
-                                               zone_start_paddr, zholes_size);
+                               zone_start_paddr, zholes_size, pmap);
 }
 
 #endif /* !CONFIG_DISCONTIGMEM */
@@ -55,7+55,7 @@ void show_free_areas_node(int nid)
 /*
  * Nodes can be initialized parallely, in no particular order.
  */
-void __init free_area_init_node(int nid, pg_data_t *pgdat, 
+void __init free_area_init_node(int nid, pg_data_t *pgdat, struct page *pmap,
        unsigned long *zones_size, unsigned long zone_start_paddr, 
        unsigned long *zholes_size)
 {
@@ -66,7+66,7 @@ void __init free_area_init_node(int nid, pg_data_t *pgdat,
                mem_map = (mem_map_t *)PAGE_OFFSET;
 
        free_area_init_core(nid, pgdat, &discard, zones_size, zone_start_paddr,
-                                               zholes_size);
+                                       zholes_size, pmap);
        pgdat->node_id = nid;
 
        /*
index 8b74a73..a7e9345 100644 (file)
@@ -532,9+532,9 @@ static inline void build_zonelists(pg_data_t *pgdat)
  */
 void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
        unsigned long *zones_size, unsigned long zone_start_paddr, 
-       unsigned long *zholes_size)
+       unsigned long *zholes_size, struct page *lmem_map)
 {
-       struct page *p, *lmem_map;
+       struct page *p;
        unsigned long i, j;
        unsigned long map_size;
        unsigned long totalpages, offset, realtotalpages;
@@ -580,9+580,11 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
         * boundary, so that MAP_NR works.
         */
        map_size = (totalpages + 1)*sizeof(struct page);
-       lmem_map = (struct page *) alloc_bootmem_node(nid, map_size);
-       lmem_map = (struct page *)(PAGE_OFFSET + 
+       if (lmem_map == (struct page *)0) {
+               lmem_map = (struct page *) alloc_bootmem_node(nid, map_size);
+               lmem_map = (struct page *)(PAGE_OFFSET + 
                        MAP_ALIGN((unsigned long)lmem_map - PAGE_OFFSET));
+       }
        *gmap = pgdat->node_mem_map = lmem_map;
        pgdat->node_size = totalpages;
        pgdat->node_start_paddr = zone_start_paddr;
@@ -664,7+666,7 @@ void __init free_area_init_core(int nid, pg_data_t *pgdat, struct page **gmap,
 
 void __init free_area_init(unsigned long *zones_size)
 {
-       free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 0, 0);
+       free_area_init_core(0, NODE_DATA(0), &mem_map, zones_size, 0, 0, 0);
 }
 
 static int __init setup_mem_frac(char *str)
index a6ee736..c670dd5 100644 (file)
@@ -868,25+868,6 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
        br_read_unlock(BR_NETPROTO_LOCK);
 }
 
-/*
- *     Fast path for loopback frames.
- */
-void dev_loopback_xmit(struct sk_buff *skb)
-{
-       struct sk_buff *newskb=skb_clone(skb, GFP_ATOMIC);
-       if (newskb==NULL)
-               return;
-
-       newskb->mac.raw = newskb->data;
-       skb_pull(newskb, newskb->nh.raw - newskb->data);
-       newskb->pkt_type = PACKET_LOOPBACK;
-       newskb->ip_summed = CHECKSUM_UNNECESSARY;
-       if (newskb->dst==NULL)
-               printk(KERN_DEBUG "BUG: packet without dst looped back 1\n");
-       netif_rx(newskb);
-}
-
 /**
  *     dev_queue_xmit - transmit a buffer
  *     @skb: buffer to transmit
index 0af9ec3..1d8002b 100644 (file)
@@ -8,7+8,7 @@
  *     the older version didn't come out right using gcc 2.5.8, the newer one
  *     seems to fall out with gcc 2.6.2.
  *
- *     Version: $Id: igmp.c,v 1.40 2000/07/26 01:04:16 davem Exp $
+ *     Version: $Id: igmp.c,v 1.41 2000/08/31 23:39:12 davem Exp $
  *
  *     Authors:
  *             Alan Cox <Alan.Cox@linux.org>
@@ -184,7+184,10 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay)
 
 #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4)
 
-static inline int igmp_send_report2(struct sk_buff *skb)
+/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook
+   changes route */
+static inline int
+output_maybe_reroute(struct sk_buff *skb)
 {
        return skb->dst->output(skb);
 }
@@ -247,7+250,7 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
        ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr));
 
        return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-                      igmp_send_report2);
+                      output_maybe_reroute);
 }
 
 
index 3d0e2b4..0567678 100644 (file)
@@ -5,7+5,7 @@
  *
  *             The Internet Protocol (IP) output module.
  *
- * Version:    $Id: ip_output.c,v 1.84 2000/08/25 02:15:47 davem Exp $
+ * Version:    $Id: ip_output.c,v 1.85 2000/08/31 23:39:12 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -107,42+107,11 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)
        return 0;
 }
 
-#ifdef CONFIG_NETFILTER
-/* To preserve the cute illusion that a locally-generated packet can
-   be mangled before routing, we actually reroute if a hook altered
-   the packet. -RR */
-static int route_me_harder(struct sk_buff *skb)
-{
-       struct iphdr *iph = skb->nh.iph;
-       struct rtable *rt;
-
-       if (ip_route_output(&rt, iph->daddr, iph->saddr,
-                           RT_TOS(iph->tos) | RTO_CONN,
-                           skb->sk ? skb->sk->bound_dev_if : 0)) {
-               printk("route_me_harder: No more route.\n");
-               return -EINVAL;
-       }
-
-       /* Drop old route. */
-       dst_release(skb->dst);
-
-       skb->dst = &rt->u.dst;
-       return 0;
-}
-#endif
-
-/* Do route recalc if netfilter changes skb. */
+/* Don't just hand NF_HOOK skb->dst->output, in case netfilter hook
+   changes route */
 static inline int
 output_maybe_reroute(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETFILTER
-       if (skb->nfcache & NFC_ALTERED) {
-               if (route_me_harder(skb) != 0) {
-                       kfree_skb(skb);
-                       return -EINVAL;
-               }
-       }
-#endif
        return skb->dst->output(skb);
 }
 
@@ -312,25+281,6 @@ static inline int ip_queue_xmit2(struct sk_buff *skb)
        struct net_device *dev;
        struct iphdr *iph = skb->nh.iph;
 
-#ifdef CONFIG_NETFILTER
-       /* BLUE-PEN-FOR-ALEXEY.  I don't understand; you mean I can't
-           hold the route as I pass the packet to userspace? -- RR
-
-          You may hold it, if you really hold it. F.e. if netfilter
-          does not destroy handed skb with skb->dst attached, it
-          will be held. When it was stored in info->arg, then
-          it was not held apparently. Now (without second arg) it is evident,
-          that it is clean.                               --ANK
-        */
-       if (rt==NULL || (skb->nfcache & NFC_ALTERED)) {
-               if (route_me_harder(skb) != 0) {
-                       kfree_skb(skb);
-                       return -EHOSTUNREACH;
-               }
-               rt = (struct rtable *)skb->dst;
-       }
-#endif
-
        dev = rt->u.dst.dev;
 
        /* This can happen when the transport layer has segments queued
index 3334a64..c6de039 100644 (file)
@@ -161,6+161,34 @@ ip_nat_out(unsigned int hooknum,
        return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }
 
+/* FIXME: change in oif may mean change in hh_len.  Check and realloc
+   --RR */
+static int
+route_me_harder(struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->nh.iph;
+       struct rtable *rt;
+       struct rt_key key = { dst:iph->daddr,
+                             src:iph->saddr,
+                             oif:skb->sk ? skb->sk->bound_dev_if : 0,
+                             tos:RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+                             fwmark:skb->nfmark
+#endif
+                           };
+
+       if (ip_route_output_key(&rt, &key) != 0) {
+               printk("route_me_harder: No more route.\n");
+               return -EINVAL;
+       }
+
+       /* Drop old route. */
+       dst_release(skb->dst);
+
+       skb->dst = &rt->u.dst;
+       return 0;
+}
+
 static unsigned int
 ip_nat_local_fn(unsigned int hooknum,
                struct sk_buff **pskb,
@@ -168,12+196,23 @@ ip_nat_local_fn(unsigned int hooknum,
                const struct net_device *out,
                int (*okfn)(struct sk_buff *))
 {
+       u_int32_t saddr, daddr;
+       unsigned int ret;
+
        /* root is playing with raw sockets. */
        if ((*pskb)->len < sizeof(struct iphdr)
            || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
                return NF_ACCEPT;
 
-       return ip_nat_fn(hooknum, pskb, in, out, okfn);
+       saddr = (*pskb)->nh.iph->saddr;
+       daddr = (*pskb)->nh.iph->daddr;
+
+       ret = ip_nat_fn(hooknum, pskb, in, out, okfn);
+       if (ret != NF_DROP && ret != NF_STOLEN
+           && ((*pskb)->nh.iph->saddr != saddr
+               || (*pskb)->nh.iph->daddr != daddr))
+               return route_me_harder(*pskb) == 0 ? ret : NF_DROP;
+       return ret;
 }
 
 /* We must be after connection tracking and before packet filtering. */
index cb9f18d..f58cd8b 100644 (file)
@@ -5,6+5,11 @@
  */
 #include <linux/module.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/route.h>
+#include <linux/ip.h>
 
 #define MANGLE_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
 
@@ -86,6+91,34 @@ ipt_hook(unsigned int hook,
        return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
 }
 
+/* FIXME: change in oif may mean change in hh_len.  Check and realloc
+   --RR */
+static int
+route_me_harder(struct sk_buff *skb)
+{
+       struct iphdr *iph = skb->nh.iph;
+       struct rtable *rt;
+       struct rt_key key = { dst:iph->daddr,
+                             src:iph->saddr,
+                             oif:skb->sk ? skb->sk->bound_dev_if : 0,
+                             tos:RT_TOS(iph->tos)|RTO_CONN,
+#ifdef CONFIG_IP_ROUTE_FWMARK
+                             fwmark:skb->nfmark
+#endif
+                           };
+
+       if (ip_route_output_key(&rt, &key) != 0) {
+               printk("route_me_harder: No more route.\n");
+               return -EINVAL;
+       }
+
+       /* Drop old route. */
+       dst_release(skb->dst);
+
+       skb->dst = &rt->u.dst;
+       return 0;
+}
+
 static unsigned int
 ipt_local_out_hook(unsigned int hook,
                   struct sk_buff **pskb,
@@ -93,6+126,11 @@ ipt_local_out_hook(unsigned int hook,
                   const struct net_device *out,
                   int (*okfn)(struct sk_buff *))
 {
+       unsigned int ret;
+       u_int8_t tos;
+       u_int32_t saddr, daddr;
+       unsigned long nfmark;
+
        /* root is playing with raw sockets. */
        if ((*pskb)->len < sizeof(struct iphdr)
            || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
@@ -101,7+139,22 @@ ipt_local_out_hook(unsigned int hook,
                return NF_ACCEPT;
        }
 
-       return ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
+       /* Save things which could affect route */
+       nfmark = (*pskb)->nfmark;
+       saddr = (*pskb)->nh.iph->saddr;
+       daddr = (*pskb)->nh.iph->daddr;
+       tos = (*pskb)->nh.iph->tos;
+
+       ret = ipt_do_table(pskb, hook, in, out, &packet_mangler, NULL);
+       /* Reroute for ANY change. */
+       if (ret != NF_DROP && ret != NF_STOLEN
+           && ((*pskb)->nh.iph->saddr != saddr
+               || (*pskb)->nh.iph->daddr != daddr
+               || (*pskb)->nfmark != nfmark
+               || (*pskb)->nh.iph->tos != tos))
+               return route_me_harder(*pskb) == 0 ? ret : NF_DROP;
+
+       return ret;
 }
 
 static struct nf_hook_ops ipt_ops[]
index d4e9806..4b7f076 100644 (file)
@@ -5,7+5,7 @@
  *
  *             ROUTE - implementation of the IP router.
  *
- * Version:    $Id: route.c,v 1.89 2000/08/09 11:59:04 davem Exp $
+ * Version:    $Id: route.c,v 1.90 2000/08/31 23:39:12 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1610,7+1610,7 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,
  * Major route resolver routine.
  */
 
-int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
+int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
 {
        struct rt_key key;
        struct fib_result res;
@@ -1620,25+1620,31 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
        unsigned hash;
        int free_res = 0;
        int err;
+       u32 tos;
 
-       tos &= IPTOS_RT_MASK|RTO_ONLINK;
-       key.dst = daddr;
-       key.src = saddr;
+       tos = oldkey->tos & (IPTOS_RT_MASK|RTO_ONLINK);
+       key.dst = oldkey->dst;
+       key.src = oldkey->src;
        key.tos = tos&IPTOS_RT_MASK;
        key.iif = loopback_dev.ifindex;
-       key.oif = oif;
+       key.oif = oldkey->oif;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+       key.fwmark = oldkey->fwmark;
+#endif
        key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
        res.fi = NULL;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
        res.r = NULL;
 #endif
 
-       if (saddr) {
-               if (MULTICAST(saddr) || BADCLASS(saddr) || ZERONET(saddr))
+       if (oldkey->src) {
+               if (MULTICAST(oldkey->src)
+                   || BADCLASS(oldkey->src)
+                   || ZERONET(oldkey->src))
                        return -EINVAL;
 
                /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
-               dev_out = ip_dev_find(saddr);
+               dev_out = ip_dev_find(oldkey->src);
                if (dev_out == NULL)
                        return -EINVAL;
 
@@ -1650,8+1656,8 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
                      of another iface. --ANK
                 */
 
-               if (oif == 0 &&
-                       (MULTICAST(daddr) || daddr == 0xFFFFFFFF)) {
+               if (oldkey->oif == 0
+                   && (MULTICAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF)) {
                        /* Special hack: user can direct multicasts
                           and limited broadcast via necessary interface
                           without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -1674,8+1680,8 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
                        dev_put(dev_out);
                dev_out = NULL;
        }
-       if (oif) {
-               dev_out = dev_get_by_index(oif);
+       if (oldkey->oif) {
+               dev_out = dev_get_by_index(oldkey->oif);
                if (dev_out == NULL)
                        return -ENODEV;
                if (__in_dev_get(dev_out) == NULL) {
@@ -1683,15+1689,15 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
                        return -ENODEV; /* Wrong error code */
                }
 
-               if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF) {
+               if (LOCAL_MCAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF) {
                        if (!key.src)
                                key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
                        goto make_route;
                }
                if (!key.src) {
-                       if (MULTICAST(daddr))
+                       if (MULTICAST(oldkey->dst))
                                key.src = inet_select_addr(dev_out, 0, key.scope);
-                       else if (!daddr)
+                       else if (!oldkey->dst)
                                key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
                }
        }
@@ -1712,7+1718,7 @@ int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int
 
        if (fib_lookup(&key, &res)) {
                res.fi = NULL;
-               if (oif) {
+               if (oldkey->oif) {
                        /* Apparently, routing tables are wrong. Assume,
                           that the destination is on link.
 
@@ -1800,7+1806,7 @@ make_route:
        } else if (res.type == RTN_MULTICAST) {
                flags |= RTCF_MULTICAST|RTCF_LOCAL;
                read_lock(&inetdev_lock);
-               if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), daddr))
+               if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), oldkey->dst))
                        flags &= ~RTCF_LOCAL;
                read_unlock(&inetdev_lock);
                /* If multicast route do not exist use
@@ -1819,18+1825,21 @@ make_route:
 
        atomic_set(&rth->u.dst.__refcnt, 1);
        rth->u.dst.flags= DST_HOST;
-       rth->key.dst    = daddr;
+       rth->key.dst    = oldkey->dst;
        rth->key.tos    = tos;
-       rth->key.src    = saddr;
+       rth->key.src    = oldkey->src;
        rth->key.iif    = 0;
-       rth->key.oif    = oif;
+       rth->key.oif    = oldkey->oif;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+       rth->key.fwmark = oldkey->fwmark;
+#endif
        rth->rt_dst     = key.dst;
        rth->rt_src     = key.src;
 #ifdef CONFIG_IP_ROUTE_NAT
        rth->rt_dst_map = key.dst;
        rth->rt_src_map = key.src;
 #endif
-       rth->rt_iif     = oif ? : dev_out->ifindex;
+       rth->rt_iif     = oldkey->oif ? : dev_out->ifindex;
        rth->u.dst.dev  = dev_out;
        dev_hold(dev_out);
        rth->rt_gateway = key.dst;
@@ -1850,7+1859,7 @@ make_route:
                if (res.type == RTN_MULTICAST) {
                        struct in_device *in_dev = in_dev_get(dev_out);
                        if (in_dev) {
-                               if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(daddr)) {
+                               if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldkey->dst)) {
                                        rth->u.dst.input = ip_mr_input;
                                        rth->u.dst.output = ip_mc_output;
                                }
@@ -1864,7+1873,7 @@ make_route:
 
        rth->rt_flags = flags;
 
-       hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
+       hash = rt_hash_code(oldkey->dst, oldkey->src^(oldkey->oif<<5), tos);
        err = rt_intern_hash(hash, rth, rp);
 done:
        if (free_res)
@@ -1881,21+1890,24 @@ e_nobufs:
        goto done;
 }
 
-int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
+int ip_route_output_key(struct rtable **rp, const struct rt_key *key)
 {
        unsigned hash;
        struct rtable *rth;
 
-       hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
+       hash = rt_hash_code(key->dst, key->src^(key->oif<<5), key->tos);
 
        read_lock_bh(&rt_hash_table[hash].lock);
        for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
-               if (rth->key.dst == daddr &&
-                   rth->key.src == saddr &&
+               if (rth->key.dst == key->dst &&
+                   rth->key.src == key->src &&
                    rth->key.iif == 0 &&
-                   rth->key.oif == oif &&
-                   !((rth->key.tos^tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
-                   ((tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
+                   rth->key.oif == key->oif &&
+#ifdef CONFIG_IP_ROUTE_FWMARK
+                   rth->key.fwmark == key->fwmark &&
+#endif
+                   !((rth->key.tos^key->tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
+                   ((key->tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
                ) {
                        rth->u.dst.lastuse = jiffies;
                        dst_hold(&rth->u.dst);
@@ -1907,8+1919,8 @@ int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
        }
        read_unlock_bh(&rt_hash_table[hash].lock);
 
-       return ip_route_output_slow(rp, daddr, saddr, tos, oif);
-}
+       return ip_route_output_slow(rp, key);
+}      
 
 #ifdef CONFIG_RTNETLINK
 
index 4274045..187fbbc 100644 (file)
@@ -1,7+1,7 @@
 /*
  * sysctl_net_ipv4.c: sysctl interface to net IPV4 subsystem.
  *
- * $Id: sysctl_net_ipv4.c,v 1.44 2000/08/09 11:59:04 davem Exp $
+ * $Id: sysctl_net_ipv4.c,v 1.45 2000/09/06 23:30:29 davem Exp $
  *
  * Begun April 1, 1996, Mike Shaver.
  * Added /proc/sys/net/ipv4 directory entry (empty =) ). [MS]
@@ -213,8+213,10 @@ ctl_table ipv4_table[] = {
         &sysctl_tcp_fack, sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_TCP_REORDERING, "tcp_reordering",
         &sysctl_tcp_reordering, sizeof(int), 0644, NULL, &proc_dointvec},
+#ifdef CONFIG_INET_ECN
        {NET_TCP_ECN, "tcp_ecn",
         &sysctl_tcp_ecn, sizeof(int), 0644, NULL, &proc_dointvec},
+#endif
        {NET_TCP_DSACK, "tcp_dsack",
         &sysctl_tcp_dsack, sizeof(int), 0644, NULL, &proc_dointvec},
        {NET_TCP_MEM, "tcp_mem",
index 76791d7..ff40ffb 100644 (file)
@@ -5,7+5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_input.c,v 1.198 2000/08/15 20:15:23 davem Exp $
+ * Version:    $Id: tcp_input.c,v 1.199 2000/09/06 23:30:29 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -73,7+73,11 @@ int sysctl_tcp_window_scaling = 1;
 int sysctl_tcp_sack = 1;
 int sysctl_tcp_fack = 1;
 int sysctl_tcp_reordering = TCP_FASTRETRANS_THRESH;
+#ifdef CONFIG_INET_ECN
 int sysctl_tcp_ecn = 1;
+#else
+int sysctl_tcp_ecn = 0;
+#endif
 int sysctl_tcp_dsack = 1;
 int sysctl_tcp_app_win = 31;
 int sysctl_tcp_adv_win_scale = 2;
index cf39195..f8cf5e5 100644 (file)
@@ -5,7+5,7 @@
  *
  *             Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:    $Id: tcp_minisocks.c,v 1.2 2000/08/28 04:32:52 davem Exp $
+ * Version:    $Id: tcp_minisocks.c,v 1.3 2000/09/05 23:13:48 davem Exp $
  *
  * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
  *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -673,6+673,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
                newsk->done = 0;
                newsk->proc = 0;
                newsk->backlog.head = newsk->backlog.tail = NULL;
+               newsk->callback_lock = RW_LOCK_UNLOCKED;
                skb_queue_head_init(&newsk->error_queue);
                newsk->write_space = tcp_write_space;
 #ifdef CONFIG_FILTER
index a7be82c..8579c5b 100644 (file)
@@ -212,7+212,7 @@ EXPORT_SYMBOL(br_ioctl_hook);
 EXPORT_SYMBOL(inetdev_lock);
 EXPORT_SYMBOL(inet_add_protocol);
 EXPORT_SYMBOL(inet_del_protocol);
-EXPORT_SYMBOL(ip_route_output);
+EXPORT_SYMBOL(ip_route_output_key);
 EXPORT_SYMBOL(ip_route_input);
 EXPORT_SYMBOL(icmp_send);
 EXPORT_SYMBOL(icmp_reply);
@@ -364,7+364,6 @@ EXPORT_SYMBOL(tcp_cwnd_application_limited);
 EXPORT_SYMBOL(xrlim_allow);
 
 EXPORT_SYMBOL(tcp_write_xmit);
-EXPORT_SYMBOL(dev_loopback_xmit);
 
 EXPORT_SYMBOL(tcp_v4_remember_stamp); 
 
close