]> git.neil.brown.name Git - history.git/commitdiff
Import 2.4.0-test3pre1 2.4.0-test3pre1
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:35:59 +0000 (15:35 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:35:59 +0000 (15:35 -0500)
138 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Makefile
arch/alpha/Makefile
arch/alpha/config.in
arch/alpha/kernel/core_cia.c
arch/alpha/kernel/pci.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/vmlinux.lds [deleted file]
arch/alpha/vmlinux.lds.in [new file with mode: 0644]
arch/arm/config.in
arch/arm/kernel/armksyms.c
arch/arm/kernel/arthur.c
arch/arm/kernel/bios32.c
arch/arm/kernel/dma-footbridge.c
arch/arm/kernel/dma-rpc.c
arch/arm/kernel/dma.c
arch/arm/kernel/ecard.c
arch/arm/kernel/hw-footbridge.c
arch/arm/kernel/hw-sa1100.c
arch/arm/kernel/irq.c
arch/arm/kernel/isa.c
arch/arm/kernel/leds-footbridge.c
arch/arm/kernel/leds-sa1100.c
arch/arm/kernel/process.c
arch/arm/kernel/ptrace.c
arch/arm/kernel/ptrace.h [new file with mode: 0644]
arch/arm/kernel/semaphore.c
arch/arm/kernel/setup.c
arch/arm/kernel/signal.c
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/mm/fault-common.c
arch/arm/mm/mm-armv.c
arch/arm/mm/proc-arm2,3.S
arch/arm/mm/proc-arm6,7.S
arch/arm/mm/proc-arm720.S
arch/i386/kernel/pci-irq.c
arch/sparc/kernel/sys_sparc.c
arch/sparc/kernel/sys_sunos.c
arch/sparc64/kernel/sys_sparc.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/sys_sunos32.c
drivers/acorn/char/Makefile
drivers/acorn/char/defkeymap-acorn.c [new file with mode: 0644]
drivers/atm/fore200e.c
drivers/block/elevator.c
drivers/block/ll_rw_blk.c
drivers/char/Makefile
drivers/char/dz.c
drivers/net/am79c961a.h
drivers/net/sk_mca.c
drivers/pnp/isapnp.c
drivers/scsi/aic7xxx.c
drivers/scsi/hosts.c
drivers/scsi/qlogicfc.c
drivers/scsi/qlogicfc.h
drivers/scsi/st.c
drivers/sound/vidc.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/usb-serial.h
drivers/usb/serial/usbserial.c
drivers/usb/serial/visor.c
drivers/video/sisfb.c
fs/binfmt_elf.c
fs/binfmt_em86.c
fs/binfmt_misc.c
fs/binfmt_script.c
fs/block_dev.c
fs/buffer.c
fs/exec.c
fs/ext2/super.c
fs/fcntl.c
fs/file_table.c
fs/hpfs/namei.c
fs/ioctl.c
fs/namei.c
fs/nfsd/export.c
fs/nfsd/nfscache.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsfh.c
fs/nfsd/nfsproc.c
fs/nfsd/nfssvc.c
fs/nfsd/vfs.c
fs/pipe.c
fs/proc/base.c
fs/qnx4/inode.c
fs/super.c
fs/sysv/inode.c
fs/udf/super.c
include/asm-alpha/pci.h
include/asm-alpha/system.h
include/asm-arm/arch-arc/ide.h
include/asm-arm/arch-cl7500/ide.h
include/asm-arm/arch-ebsa285/ide.h
include/asm-arm/arch-l7200/ide.h
include/asm-arm/arch-nexuspci/ide.h
include/asm-arm/arch-rpc/ide.h
include/asm-arm/arch-sa1100/ide.h
include/asm-arm/arch-sa1100/irq.h
include/asm-arm/arch-shark/hardware.h
include/asm-arm/arch-shark/ide.h
include/asm-arm/atomic.h
include/asm-arm/cpu-multi26.h
include/asm-arm/dma.h
include/asm-arm/floppy.h
include/asm-arm/io.h
include/asm-arm/memory.h [new file with mode: 0644]
include/asm-arm/proc-armo/system.h
include/asm-arm/proc-armv/system.h
include/asm-arm/ptrace.h
include/asm-arm/system.h
include/linux/fs.h
include/linux/mm.h
include/linux/mount.h
include/linux/nfsd/cache.h
include/linux/nfsd/export.h
include/linux/nfsd/nfsd.h
include/linux/nfsd/nfsfh.h
include/linux/pci_ids.h
include/linux/socket.h
include/linux/vmalloc.h
ipc/shm.c
kernel/exec_domain.c
kernel/ksyms.c
kernel/module.c
kernel/sched.c
kernel/sysctl.c
mm/filemap.c
mm/mmap.c
mm/page_alloc.c
mm/swap_state.c
mm/swapfile.c
mm/vmalloc.c
net/netsyms.c
net/sunrpc/svcsock.c
net/unix/af_unix.c

diff --git a/CREDITS b/CREDITS
index 53968d7772038103946d125b3f48b53539961a32..5ca87fc5de3eb1ce390635576ba984ffc6865e1e 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -950,7 +950,7 @@ S: London SE16 1GD
 S: United Kingdom
 
 N: Kai Harrekilde-Petersen
-E: khp@olicom.dk
+E: kai.harrekilde@get2net.dk
 D: Original author of the ftape-HOWTO, i82078 fdc detection code.
 
 N: Bart Hartgers
index 0b9e549fc6f7b522467b8f0df8433811dc316681..525932df1ecbdef1e0aeee68c705749e6c1a49f2 100644 (file)
@@ -41,7 +41,7 @@ Card) hardware, for example, you probably needn't concern yourself
 with pcmcia-cs.
 
 o  Gnu C                  2.7.2.3                 # gcc --version
-o  binutils               2.9.1.0.              # ld -v
+o  binutils               2.9.1.0.22              # ld -v
 o  util-linux             2.10g                   # chsh -v
 o  modutils               2.3.10                  # insmod -V
 o  e2fsprogs              1.18                    # /sbin/tune2fs --version
@@ -78,7 +78,7 @@ release of binutils.
 
 If you can, upgrade to the latest 2.9.5 binutils release.  Older
 releases such as 2.8, 2.8.xx, and the FSF's 2.9.1 should be avoided if
-at all possible.  The later releases of 2.9.1.0.x (anything where x >= 7)
+at all possible.  The later releases of 2.9.1.0.x (anything where x >= 22)
 can and do compile the kernel properly, but there are many benefits
 to upgrading to 2.9.5 if you're up to it.
 
@@ -248,8 +248,8 @@ o  ftp://ftp.varesearch.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.t
 
 2.9.5 series
 ------------
-o  ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.29.tar.gz
-     <ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.29.tar.bz2>
+o  ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.gz
+     <ftp://ftp.varesearch.com/pub/support/hjl/binutils/binutils-2.9.5.0.46.tar.bz2>
 
 System utilities
 ****************
index bc937c738ce78ed90fd2ab108c477bdb4783dfae..b988920bb9f31e918025c2c3d56d410bf9676351 100644 (file)
@@ -2126,6 +2126,20 @@ CONFIG_ALPHA_SRM
 
   If unsure, say N.
 
+Legacy kernel start address
+CONFIG_ALPHA_LEGACY_START_ADDRESS
+  The 2.4 kernel changed the kernel start address from 0x310000
+  to 0x810000 to make room for the Wildfire's larger SRM console.
+
+  If you're using aboot 0.7 or later, the bootloader will examine
+  the ELF headers to determine where to transfer control.  Unfortunately,
+  most older bootloaders -- APB, or MILO -- hardcoded the kernel
+  start address rather than examining the ELF headers, and the result
+  is a hard lockup.
+
+  Say Y if you have a broken bootloader.  Say N if you do not, or
+  if you wish to run on Wildfire.
+
 Non-standard serial port support
 CONFIG_SERIAL_NONSTANDARD
   Say Y here if you have any non-standard serial boards -- boards
@@ -3250,6 +3264,14 @@ CONFIG_FB_VIRTUAL
  
   If unsure, say N.
 
+CONFIG_FB_SA1100
+  This is a framebuffer device for the SA-1100 LCD Controller.
+  See http://www.linux-fbdev.org/ for information on framebuffer
+  devices.
+
+  If you plan to use the LCD display with your SA-1100 system, say
+  Y here.
+
 Advanced low level driver options
 CONFIG_FBCON_ADVANCED
   The frame buffer console uses character drawing routines that are
@@ -15440,6 +15462,20 @@ CONFIG_ARCH_PERSONAL_SERVER
   If you have any questions or comments about the  Compaq Personal
   Server, send e-mail to skiff@crl.dec.com
 
+Include support for Assabet
+CONFIG_SA1100_ASSABET
+  Say Y here if you are using the Intel(R) StrongARM(R) SA-1110
+  Microprocessor Development Board (also known as the Assabet).
+
+Include support for the Compaq iPAQ 3600
+CONFIG_SA1100_BITSY
+  Say Y here if you intend to run this kernel on the Compaq iPAQ 3600
+  handheld computer.  Information about this machine and the Linux
+  port to this machine can be found at:
+
+  http://www.handhelds.org/Compaq/index.html#iPAQ_H3600
+  http://www.compaq.com/products/handhelds/pocketpc/
+
 Math emulation
 CONFIG_NWFPE
   Say Y to include the NWFPE floating point emulator in the kernel.
@@ -15496,6 +15532,17 @@ CONFIG_DEBUG_INFO
   time and disk space needed for compilation of the kernel. If in
   doubt say N.
 
+Kernel low-level debugging functions
+CONFIG_DEBUG_LL
+  Say Y here to include definitions of printascii, printchar, printhex
+  in the kernel.  This is helpful if you are debugging code that
+  executes before the console is initialized.
+
+Kernel low-level debugging messages via footbridge serial port
+CONFIG_DEBUG_DC21285_PORT
+  Say Y here if you want the low-level print routines to direct their
+  output to the serial port in the DC21285 (Footbridge).
+
 Split initialisation functions into discardable section
 CONFIG_TEXT_SECTIONS
   If you say Y here, kernel code that is only used during
index 523de4e0f7e05e975351c97f31b3c743a4dda5d6..7fdcef74cbd85028acf0cface407aff5546abb71 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -test2
+EXTRAVERSION = -test3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
index 36f4d4e6df9f402fe8c8bcf1c118ca294c366633..3daa2c73cdd8420ab0d7d5b217367007e90ff0c1 100644 (file)
@@ -10,7 +10,7 @@
 
 NM := nm -B
 
-LINKFLAGS = -static -T arch/alpha/vmlinux.lds #-N -relax
+LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N #-relax
 CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
 
 # Determine if we can use the BWX instructions with GAS.
@@ -90,7 +90,7 @@ endif
 
 LIBS := $(TOPDIR)/arch/alpha/lib/lib.a $(LIBS) $(TOPDIR)/arch/alpha/lib/lib.a
 
-MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+MAKEBOOT = $(MAKE) -C arch/alpha/boot
 
 rawboot:
        @$(MAKEBOOT) rawboot
@@ -109,13 +109,15 @@ srmboot:
        @$(MAKEBOOT) srmboot
 
 archclean:
-       @$(MAKE) -C arch/$(ARCH)/kernel clean
+       @$(MAKE) -C arch/alpha/kernel clean
        @$(MAKEBOOT) clean
+       rm -f arch/alpha/vmlinux.lds
 
 archmrproper:
 
 archdep:
        @$(MAKEBOOT) dep
+       $(CPP) $(CPPFLAGS) -xc -P arch/alpha/vmlinux.lds.in -o arch/alpha/vmlinux.lds
 
 bootpfile:
        @$(MAKEBOOT) bootpfile
index 5f344e0f57ef52eba1100f6b639efb76e6af114d..7441083b6d49ab053a08ffa77d0e051d87f21083 100644 (file)
@@ -331,7 +331,6 @@ source drivers/usb/Config.in
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Kernel FP software completion' CONFIG_MATHEMU
 else
@@ -339,4 +338,7 @@ else
 fi
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+
+bool 'Legacy kernel start address' CONFIG_ALPHA_LEGACY_START_ADDRESS
+
 endmenu
index 88c88a4e61a372aa6c6f315e919aa964425b376e..348bd843f2d449667162785d32fede685b673796 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <asm/system.h>
 #include <asm/ptrace.h>
+#include <asm/hwrpb.h>
 
 #define __EXTERN_INLINE inline
 #include <asm/io.h>
@@ -712,6 +713,25 @@ cia_init_arch(void)
 void __init
 pyxis_init_arch(void)
 {
+       /* On pyxis machines we can precisely calculate the
+          CPU clock frequency using pyxis real time counter.
+          It's especially useful for SX164 with broken RTC.
+
+          Both CPU and chipset are driven by the single 16.666M
+          or 16.667M crystal oscillator. PYXIS_RT_COUNT clock is
+          66.66 MHz. -ink */
+
+       unsigned int cc0, cc1;
+       unsigned long pyxis_cc;
+
+       __asm__ __volatile__ ("rpcc %0" : "=r"(cc0));
+       pyxis_cc = *(vulp)PYXIS_RT_COUNT;
+       do { } while(*(vulp)PYXIS_RT_COUNT - pyxis_cc < 4096);
+       __asm__ __volatile__ ("rpcc %0" : "=r"(cc1));
+       cc1 -= cc0;
+       hwrpb->cycle_freq = ((cc1 >> 11) * 100000000UL) / 3;
+       hwrpb_update_checksum(hwrpb);
+
        do_init_arch(1);
 }
 
index 7a916ad08b9b078e1a0176f50f3b740a5db0ae27..2dc6f00ddce7cba5fd4e00017492c649805f77d1 100644 (file)
@@ -369,6 +369,22 @@ pcibios_enable_device(struct pci_dev *dev)
        return 0;
 }
 
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain firmware forgets to set it properly, as seen
+ *  on SX164 and LX164 with SRM.
+ */
+void
+pcibios_set_master(struct pci_dev *dev)
+{
+       u8 lat;
+       pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+       if (lat >= 16) return;
+       printk("PCI: Setting latency timer of device %s to 64\n",
+                                                       dev->slot_name);
+       pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+}
+
 #define ROUND_UP(x, a)         (((x) + (a) - 1) & ~((a) - 1))
 
 static void __init
index b98e460283120ae236ae45c0aac0763bf2b7cb70..19abbb6c3bb33926382bfe6a23d56487782e0310 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/core_cia.h>
+#include <asm/hwrpb.h>
 
 #include "proto.h"
 #include "irq_impl.h"
@@ -114,6 +115,36 @@ sx164_init_pci(void)
        SMC669_Init(0);
 }
 
+static void __init
+sx164_init_arch(void)
+{
+       /*
+        * OSF palcode v1.23 forgets to enable PCA56 Motion Video
+        * Instructions. Let's enable it.
+        * We have to check palcode revision because CSERVE interface
+        * is subject to change without notice. For example, it
+        * has been changed completely since v1.16 (found in MILO
+        * distribution). -ink
+        */
+       struct percpu_struct *cpu = (struct percpu_struct*)
+               ((char*)hwrpb + hwrpb->processor_offset);
+
+       if (alpha_using_srm && (cpu->pal_revision & 0xffff) == 0x117) {
+               __asm__ __volatile__(
+               "lda    $16,8($31)\n"
+               "call_pal 9\n"          /* Allow PALRES insns in kernel mode */
+               ".long  0x64000118\n\n" /* hw_mfpr $0,icsr */
+               "ldah   $16,(1<<(19-16))($31)\n"
+               "or     $0,$16,$0\n"    /* set MVE bit */
+               ".long  0x74000118\n"   /* hw_mtpr $0,icsr */
+               "lda    $16,9($31)\n"
+               "call_pal 9"            /* Disable PALRES insns */
+               : : : "$0", "$16");
+               printk("PCA56 MVI set enabled\n");
+       }
+
+       pyxis_init_arch();
+}
 
 /*
  * The System Vector
@@ -133,7 +164,7 @@ struct alpha_machine_vector sx164_mv __initmv = {
        nr_irqs:                48,
        device_interrupt:       pyxis_device_interrupt,
 
-       init_arch:              pyxis_init_arch,
+       init_arch:              sx164_init_arch,
        init_irq:               sx164_init_irq,
        init_rtc:               common_init_rtc,
        init_pci:               sx164_init_pci,
diff --git a/arch/alpha/vmlinux.lds b/arch/alpha/vmlinux.lds
deleted file mode 100644 (file)
index f64a926..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-OUTPUT_FORMAT("elf64-alpha")
-ENTRY(__start)
-SECTIONS
-{
-  . = 0xfffffc0000810000;
-  _text = .;
-  .text : { *(.text) }
-  _etext = .;
-
-  /* Exception table */
-  . = ALIGN(16);
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  /* Kernel symbol table */
-  . = ALIGN(8);
-  __start___ksymtab = .;
-  __ksymtab : { *(__ksymtab) }
-  __stop___ksymtab = .;
-  .kstrtab : { *(.kstrtab) }
-
-  /* Startup code */
-  . = ALIGN(8192);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-
-  . = ALIGN(8);
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-
-  . = ALIGN(2*8192);   /* Align double page for init_task_union */
-  __init_end = .;
-
-  /* The initial task and kernel stack */
-  init_task : { *(init_task) }
-
-  /* Global data */
-  _data = .;
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-  .rodata : { *(.rodata) }
-  .data : { *(.data) CONSTRUCTORS }
-  .got : { *(.got) }
-  .sdata : { *(.sdata) }
-  _edata = .;
-
-  __bss_start = .;
-  .sbss : { *(.sbss) *(.scommon) }
-  .bss : { *(.bss) *(COMMON) }
-  __bss_stop = .;
-  _end = .;
-
-  .mdebug 0 : { *(.mdebug) }
-  .note 0 : { *(.note) }
-  .comment 0 : { *(.comment) }
-
-  /* DWARF 1 */
-  .debug          0 : { *(.debug) }
-  .line           0 : { *(.line) }
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  /* DWARF 2 */
-  .debug_info     0 : { *(.debug_info) }
-  .debug_abbrev   0 : { *(.debug_abbrev) }
-  .debug_line     0 : { *(.debug_line) }
-  .debug_frame    0 : { *(.debug_frame) }
-  .debug_str      0 : { *(.debug_str) }
-  .debug_loc      0 : { *(.debug_loc) }
-  .debug_macinfo  0 : { *(.debug_macinfo) }
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames 0 : { *(.debug_weaknames) }
-  .debug_funcnames 0 : { *(.debug_funcnames) }
-  .debug_typenames 0 : { *(.debug_typenames) }
-  .debug_varnames  0 : { *(.debug_varnames) }
-
-  /DISCARD/ : { *(.text.exit) *(.data.exit) }
-}
diff --git a/arch/alpha/vmlinux.lds.in b/arch/alpha/vmlinux.lds.in
new file mode 100644 (file)
index 0000000..a153e5b
--- /dev/null
@@ -0,0 +1,96 @@
+#include <linux/config.h>
+
+OUTPUT_FORMAT("elf64-alpha")
+ENTRY(__start)
+PHDRS { kernel PT_LOAD ; }
+SECTIONS
+{
+#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
+  . = 0xfffffc0000310000;
+#else
+  . = 0xfffffc0000810000;
+#endif
+
+  _text = .;
+  .text : { *(.text) } :kernel
+  _etext = .;
+
+  /* Exception table */
+  . = ALIGN(16);
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  /* Kernel symbol table */
+  . = ALIGN(8);
+  __start___ksymtab = .;
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+  .kstrtab : { *(.kstrtab) }
+
+  /* Startup code */
+  . = ALIGN(8192);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+
+  . = ALIGN(8);
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+
+  . = ALIGN(2*8192);   /* Align double page for init_task_union */
+  __init_end = .;
+
+  /* The initial task and kernel stack */
+  init_task : { *(init_task) }
+
+  /* Global data */
+  _data = .;
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+  .rodata : { *(.rodata) }
+  .data : { *(.data) CONSTRUCTORS }
+  .got : { *(.got) }
+  .sdata : { *(.sdata) }
+  _edata = .;
+
+  __bss_start = .;
+  .sbss : { *(.sbss) *(.scommon) }
+  .bss : { *(.bss) *(COMMON) }
+  __bss_stop = .;
+  _end = .;
+
+  .mdebug 0 : { *(.mdebug) }
+  .note 0 : { *(.note) }
+  .comment 0 : { *(.comment) }
+
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+
+  /DISCARD/ : { *(.text.exit) *(.data.exit) }
+}
index ff683b30bfa3c373f9d7e40811ca301f8934a2c8..15fba34032df91aa062246db56f3cd463d6df423 100644 (file)
@@ -12,6 +12,7 @@ define_bool CONFIG_UID16 y
 mainmenu_option next_comment
 comment 'Code maturity level options'
 bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+bool 'Prompt for obsolete code/drivers' CONFIG_OBSOLETE
 endmenu
 
 
@@ -45,8 +46,8 @@ if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    if [ "$CONFIG_SA1100_ASSABET" = "y" ]; then
       bool '  Include support for Neponset' CONFIG_ASSABET_NEPONSET
    fi
-   bool '  Include support for Bitsy' CONFIG_SA1100_BITSY
    bool '  Include support for Brutus' CONFIG_SA1100_BRUTUS
+   bool '  Include support for Compaq iPAQ 3600 (Bitsy)' CONFIG_SA1100_BITSY
 #   bool '  Include support for Empeg' CONFIG_SA1100_EMPEG
 #   bool '  Include support for Itsy' CONFIG_SA1100_ITSY
    bool '  Include support for LART' CONFIG_SA1100_LART
@@ -342,7 +343,7 @@ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool 'Kernel low-level debugging functions' CONFIG_DEBUG_LL
    if [ "$CONFIG_DEBUG_LL" = "y" ]; then
       if [ "$CONFIG_FOOTBRIDGE" = "y" ]; then
-         bool 'Kernel low-level debugging messages via DC21285 port' CONFIG_DEBUG_DC21285_PORT
+         bool 'Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT
       fi
    fi
 fi
index ffd0f1b5ef86055dd5e78db6fefc35e60d651cd7..5ac0743be065634d182fb610d101e48952d81083 100644 (file)
@@ -31,6 +31,8 @@ extern void outswb(unsigned int port, const void *to, int len);
 extern unsigned int local_bh_count[NR_CPUS];
 extern unsigned int local_irq_count[NR_CPUS];
 
+extern void __bad_xchg(volatile void *ptr, int size);
+
 /*
  * syscalls
  */
@@ -90,7 +92,6 @@ EXPORT_SYMBOL(kd_mksound);
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(udelay);
-EXPORT_SYMBOL(xchg_str);
 EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(local_irq_count);
 #ifdef CONFIG_CPU_32
@@ -103,6 +104,7 @@ EXPORT_SYMBOL(system_serial_low);
 EXPORT_SYMBOL(system_serial_high);
 EXPORT_SYMBOL(mem_fclk_21285);
 EXPORT_SYMBOL(__bug);
+EXPORT_SYMBOL(__bad_xchg);
 EXPORT_SYMBOL(__readwrite_bug);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
index 8a8a5510d591769661a989fe9b6166bcdb2303c3..0547302f850196d25cfe737f9af7925010eb3adb 100644 (file)
@@ -3,8 +3,8 @@
  * Copyright (C) 1998-1999 Philip Blundell
  */
 
-#include <linux/personality.h>
 #include <linux/module.h>
+#include <linux/personality.h>
 #include <linux/stddef.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
index 2fbda24be57165d4f71d89142755e43dc268b09a..a077f13b997258b4297e9d088ef6e9592f47951d 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
-#include <linux/errno.h>
 #include <linux/init.h>
 
 #include <asm/irq.h>
index 65875831cdaef39b369699f471d4e2c1b6741a30..1d2ef26c4bdc436f5a4544d180cd6ad51655476f 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
-#include <linux/errno.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
index e1b54233b977844d46b9d05440916165f7c65070..f4bc97f1d1a7f2167544d5feb25fd385966b069b 100644 (file)
@@ -15,6 +15,7 @@
 #include <asm/fiq.h>
 #include <asm/io.h>
 #include <asm/iomd.h>
+#include <asm/irq.h>
 #include <asm/hardware.h>
 #include <asm/uaccess.h>
 
index 7d1a11cd599a38026f34577e977af7b08b6caf43..ff8322d34cabaaae0d0fdfc64c43dcb187878b3c 100644 (file)
@@ -14,9 +14,9 @@
  *
  * Moved DMA resource allocation here...
  */
+#include <linux/malloc.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
 #include <linux/mman.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
index 61eb422b21b98fcf4848eff571666623c0fa9272..b4d38e00fea827b7142a166f500ef14b758d0f7c 100644 (file)
@@ -33,9 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/malloc.h>
-#include <linux/errno.h>
 #include <linux/proc_fs.h>
-#include <linux/unistd.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
@@ -913,7 +911,6 @@ ecard_probe(int slot, card_type_t type)
        ecard_t **ecp;
        ecard_t *ec;
        struct ex_ecid cid;
-       char buffer[200];
        int i, rc = -ENOMEM;
 
        ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
@@ -994,12 +991,9 @@ ecard_probe(int slot, card_type_t type)
 nodev:
        if (rc && ec)
                kfree(ec);
-       else {
+       else
                slot_to_expcard[slot] = ec;
 
-               ecard_prints(buffer, ec);
-               printk("%s", buffer);
-       }
        return rc;
 }
 
@@ -1075,7 +1069,7 @@ void __init ecard_init(void)
        init_waitqueue_head(&ecard_done);
 #endif
 
-       printk("Probing expansion cards: (does not imply support)\n");
+       printk("Probing expansion cards\n");
 
        for (slot = 0; slot < 8; slot ++) {
                if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
index 08aac078ea84b5757df922d9449c071cbf1c0361..b56b944e7a9529e70aea0e660fede6fb5a12cd30 100644 (file)
@@ -8,19 +8,12 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/sched.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/smp.h>
-#include <linux/mm.h>
 #include <linux/init.h>
 
-#include <asm/dec21285.h>
 #include <asm/io.h>
-#include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/system.h>
 
 #define GP1_IO_BASE            0x338
 #define GP2_IO_BASE            0x33a
 
+
+#ifdef CONFIG_LEDS
+#define DEFAULT_LEDS   0
+#else
+#define DEFAULT_LEDS   GPIO_GREEN_LED
+#endif
+
 /*
  * Netwinder stuff
  */
@@ -396,9 +396,9 @@ static unsigned char rwa_unlock[] __initdata =
   0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 };
 
 #ifndef DEBUG
-#define dprintk if (0) printk
+#define dprintk(x...)
 #else
-#define dprintk printk
+#define dprintk(x...) printk(x)
 #endif
 
 #define WRITE_RWA(r,v) do { outb((r), 0x279); udelay(10); outb((v), 0xa79); } while (0)
@@ -602,74 +602,13 @@ EXPORT_SYMBOL(gpio_modify_op);
 EXPORT_SYMBOL(gpio_modify_io);
 EXPORT_SYMBOL(cpld_modify);
 
-#endif
-
-#ifdef CONFIG_LEDS
-#define DEFAULT_LEDS   0
-#else
-#define DEFAULT_LEDS   GPIO_GREEN_LED
-#endif
-
-/*
- * CATS stuff
- */
-#ifdef CONFIG_ARCH_CATS
-
-#define CONFIG_PORT    0x370
-#define INDEX_PORT     (CONFIG_PORT)
-#define DATA_PORT      (CONFIG_PORT + 1)
-
-static void __init cats_hw_init(void)
-{
-       /* Set Aladdin to CONFIGURE mode */
-       outb(0x51, CONFIG_PORT);
-       outb(0x23, CONFIG_PORT);
-
-       /* Select logical device 3 */
-       outb(0x07, INDEX_PORT);
-       outb(0x03, DATA_PORT);
-
-       /* Set parallel port to DMA channel 3, ECP+EPP1.9, 
-          enable EPP timeout */
-       outb(0x74, INDEX_PORT);
-       outb(0x03, DATA_PORT);
-       
-       outb(0xf0, INDEX_PORT);
-       outb(0x0f, DATA_PORT);
-
-       outb(0xf1, INDEX_PORT);
-       outb(0x07, DATA_PORT);
-
-       /* Select logical device 4 */
-       outb(0x07, INDEX_PORT);
-       outb(0x04, DATA_PORT);
-
-       /* UART1 high speed mode */
-       outb(0xf0, INDEX_PORT);
-       outb(0x02, DATA_PORT);
-
-       /* Select logical device 5 */
-       outb(0x07, INDEX_PORT);
-       outb(0x05, DATA_PORT);
-
-       /* UART2 high speed mode */
-       outb(0xf0, INDEX_PORT);
-       outb(0x02, DATA_PORT);
-
-       /* Set Aladdin to RUN mode */
-       outb(0xbb, CONFIG_PORT);
-}
-
-#endif
-
 /*
  * Initialise any other hardware after we've got the PCI bus
  * initialised.  We may need the PCI bus to talk to this other
  * hardware.
  */
-static int __init hw_init(void)
+static int __init nw_hw_init(void)
 {
-#ifdef CONFIG_ARCH_NETWINDER
        /*
         * this ought to have a better home...
         * Since this calls the above routines, which are
@@ -688,12 +627,66 @@ static int __init hw_init(void)
                gpio_modify_op(GPIO_RED_LED|GPIO_GREEN_LED, DEFAULT_LEDS);
                spin_unlock_irqrestore(&gpio_lock, flags);
        }
+       return 0;
+}
+
+__initcall(nw_hw_init);
 #endif
+
+/*
+ * CATS stuff
+ */
 #ifdef CONFIG_ARCH_CATS
-       if (machine_is_cats())
-               cats_hw_init();
-#endif
+
+#define CONFIG_PORT    0x370
+#define INDEX_PORT     (CONFIG_PORT)
+#define DATA_PORT      (CONFIG_PORT + 1)
+
+static int __init cats_hw_init(void)
+{
+       if (machine_is_cats()) {
+               /* Set Aladdin to CONFIGURE mode */
+               outb(0x51, CONFIG_PORT);
+               outb(0x23, CONFIG_PORT);
+
+               /* Select logical device 3 */
+               outb(0x07, INDEX_PORT);
+               outb(0x03, DATA_PORT);
+
+               /* Set parallel port to DMA channel 3, ECP+EPP1.9, 
+                  enable EPP timeout */
+               outb(0x74, INDEX_PORT);
+               outb(0x03, DATA_PORT);
+       
+               outb(0xf0, INDEX_PORT);
+               outb(0x0f, DATA_PORT);
+
+               outb(0xf1, INDEX_PORT);
+               outb(0x07, DATA_PORT);
+
+               /* Select logical device 4 */
+               outb(0x07, INDEX_PORT);
+               outb(0x04, DATA_PORT);
+
+               /* UART1 high speed mode */
+               outb(0xf0, INDEX_PORT);
+               outb(0x02, DATA_PORT);
+
+               /* Select logical device 5 */
+               outb(0x07, INDEX_PORT);
+               outb(0x05, DATA_PORT);
+
+               /* UART2 high speed mode */
+               outb(0xf0, INDEX_PORT);
+               outb(0x02, DATA_PORT);
+
+               /* Set Aladdin to RUN mode */
+               outb(0xbb, CONFIG_PORT);
+       }
+
        return 0;
 }
 
-__initcall(hw_init);
+__initcall(cats_hw_init);
+#endif
+
index 539bb721baae78de526c96a68ebe07df40dccb09..862c3a2c4c60bc249bc8249689883ff9400ba523 100644 (file)
@@ -10,9 +10,9 @@
  *
  */
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/sched.h>
 
 #include <asm/delay.h>
index 7a761b7c6b7c0a0743beb3af923da857a97a7e71..40a47c45fbdf5ed23fc488c9241dc4dfa26212be 100644 (file)
@@ -17,7 +17,6 @@
  */
 #include <linux/config.h>
 #include <linux/ptrace.h>
-#include <linux/errno.h>
 #include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
@@ -26,7 +25,6 @@
 #include <linux/malloc.h>
 #include <linux/random.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
index a5424f8b61b8d10cb0946ec4e7d26e10d860d4f4..17696acb03817b1396e2b0f0eae8ef90f14260c6 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/stddef.h>
 #include <linux/types.h>
-#include <linux/linkage.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 #include <linux/init.h>
index 4fa2237ebc6184043fe277acc9e325761ec054d4..b309c2ea329e9906e3802dcc7507a263024d3b18 100644 (file)
@@ -18,8 +18,8 @@
  *   02-05-1999        RMK     Various cleanups
  */
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
index ef6918d7cbe90c81a9e29aea41e4709e24d4dac1..f2f0325c3fa3e223bd68abe8152cf8e5ab733cc9 100644 (file)
@@ -29,8 +29,8 @@
  * 
  */
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 
index 40b3b9e7244f40b6268ca00a71f8206e8b27040f..cab969c5c79e5b6afa121428863fa5dcf303f724 100644 (file)
@@ -7,28 +7,22 @@
 
 #include <stdarg.h>
 
-#include <linux/errno.h>
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
 #include <linux/malloc.h>
-#include <linux/vmalloc.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/interrupt.h>
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 
-#include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /*
  * Values for cpu_do_idle()
index 1684c5f5f925e35cc1ff2517e34fff4b83de02db..e45e03fcbe6887caef215ce21b62fd307fdfc4b4 100644 (file)
@@ -8,7 +8,6 @@
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
 
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
+#include "ptrace.h"
+
+#define REG_PC 15
+#define REG_PSR        16
 /*
  * does not yet catch signals sent when the child dies.
  * in exit.c or in signal.c.
  */
 #define BREAKINST      0xef9f0001
 
+/*
+ * Get the address of the live pt_regs for the specified task.
+ * These are saved onto the top kernel stack when the process
+ * is not running.
+ */
+static inline struct pt_regs *
+get_user_regs(struct task_struct *task)
+{
+       return (struct pt_regs *)
+               ((unsigned long)task + 8192 - sizeof(struct pt_regs));
+}
+
 /*
  * this routine will get a word off of the processes privileged stack.
  * the offset is how far from the base addr as stored in the THREAD.
  */
 static inline long get_stack_long(struct task_struct *task, int offset)
 {
-       struct pt_regs *regs;
-
-       regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
-
-       return regs->uregs[offset];
+       return get_user_regs(task)->uregs[offset];
 }
 
 /*
@@ -47,20 +58,16 @@ static inline long get_stack_long(struct task_struct *task, int offset)
  * this routine assumes that all the privileged stacks are in our
  * data space.
  */
-static inline long put_stack_long(struct task_struct *task, int offset,
-       unsigned long data)
+static inline int
+put_stack_long(struct task_struct *task, int offset, long data)
 {
-       struct pt_regs *regs;
-
-       regs = (struct pt_regs *)((unsigned long)task + 8192 - sizeof(struct pt_regs));
-
-       regs->uregs[offset] = data;
+       get_user_regs(task)->uregs[offset] = data;
 
        return 0;
 }
 
-static int
-read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
+static inline int
+read_tsk_long(struct task_struct *child, unsigned long addr, unsigned long *res)
 {
        int copied;
 
@@ -69,8 +76,8 @@ read_long(struct task_struct *child, unsigned long addr, unsigned long *res)
        return copied != sizeof(*res) ? -EIO : 0;
 }
 
-static int
-write_long(struct task_struct *child, unsigned long addr, unsigned long val)
+static inline int
+write_tsk_long(struct task_struct *child, unsigned long addr, unsigned long val)
 {
        int copied;
 
@@ -82,35 +89,33 @@ write_long(struct task_struct *child, unsigned long addr, unsigned long val)
 /*
  * Get value of register `rn' (in the instruction)
  */
-static unsigned long ptrace_getrn (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getrn(struct task_struct *child, unsigned long insn)
 {
        unsigned int reg = (insn >> 16) & 15;
        unsigned long val;
 
+       val = get_stack_long(child, reg);
        if (reg == 15)
-               val = pc_pointer (get_stack_long (child, reg));
-       else
-               val = get_stack_long (child, reg);
+               val = pc_pointer(val);
 
-printk ("r%02d=%08lX ", reg, val);
        return val;
 }
 
 /*
  * Get value of operand 2 (in an ALU instruction)
  */
-static unsigned long ptrace_getaluop2 (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getaluop2(struct task_struct *child, unsigned long insn)
 {
        unsigned long val;
        int shift;
        int type;
 
-printk ("op2=");
        if (insn & 1 << 25) {
                val = insn & 255;
                shift = (insn >> 8) & 15;
                type = 3;
-printk ("(imm)");
        } else {
                val = get_stack_long (child, insn & 15);
 
@@ -120,9 +125,8 @@ printk ("(imm)");
                        shift = (insn >> 7) & 31;
 
                type = (insn >> 5) & 3;
-printk ("(r%02ld)", insn & 15);
        }
-printk ("sh%dx%d", type, shift);
+
        switch (type) {
        case 0: val <<= shift;  break;
        case 1: val >>= shift;  break;
@@ -133,24 +137,23 @@ printk ("sh%dx%d", type, shift);
                val = (val >> shift) | (val << (32 - shift));
                break;
        }
-printk ("=%08lX ", val);
        return val;
 }
 
 /*
  * Get value of operand 2 (in a LDR instruction)
  */
-static unsigned long ptrace_getldrop2 (struct task_struct *child, unsigned long insn)
+static unsigned long
+ptrace_getldrop2(struct task_struct *child, unsigned long insn)
 {
        unsigned long val;
        int shift;
        int type;
 
-       val = get_stack_long (child, insn & 15);
+       val = get_stack_long(child, insn & 15);
        shift = (insn >> 7) & 31;
        type = (insn >> 5) & 3;
 
-printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
        switch (type) {
        case 0: val <<= shift;  break;
        case 1: val >>= shift;  break;
@@ -161,7 +164,6 @@ printk ("op2=r%02ldsh%dx%d", insn & 15, shift, type);
                val = (val >> shift) | (val << (32 - shift));
                break;
        }
-printk ("=%08lX ", val);
        return val;
 }
 
@@ -170,95 +172,72 @@ get_branch_address(struct task_struct *child, unsigned long pc, unsigned long in
 {
        unsigned long alt = 0;
 
-printk(KERN_DEBUG "ptrace_set_bpt: insn=%08lX pc=%08lX ", insn, pc);
-       switch (insn & 0x0e100000) {
+       switch (insn & 0x0e000000) {
        case 0x00000000:
-       case 0x00100000:
-       case 0x02000000:
-       case 0x02100000: /* data processing */
-               printk ("data ");
-               switch (insn & 0x01e0f000) {
-               case 0x0000f000:
-                       alt = ptrace_getrn(child, insn) & ptrace_getaluop2(child, insn);
-                       break;
-               case 0x0020f000:
-                       alt = ptrace_getrn(child, insn) ^ ptrace_getaluop2(child, insn);
-                       break;
-               case 0x0040f000:
-                       alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn);
-                       break;
-               case 0x0060f000:
-                       alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn);
-                       break;
-               case 0x0080f000:
-                       alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn);
-                       break;
-               case 0x00a0f000:
-                       alt = ptrace_getrn(child, insn) + ptrace_getaluop2(child, insn) +
-                               (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
-                       break;
-               case 0x00c0f000:
-                       alt = ptrace_getrn(child, insn) - ptrace_getaluop2(child, insn) +
-                               (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
-                       break;
-               case 0x00e0f000:
-                       alt = ptrace_getaluop2(child, insn) - ptrace_getrn(child, insn) +
-                               (get_stack_long (child, 16/*REG_PSR*/) & CC_C_BIT ? 1 : 0);
-                       break;
-               case 0x0180f000:
-                       alt = ptrace_getrn(child, insn) | ptrace_getaluop2(child, insn);
-                       break;
-               case 0x01a0f000:
-                       alt = ptrace_getaluop2(child, insn);
-                       break;
-               case 0x01c0f000:
-                       alt = ptrace_getrn(child, insn) & ~ptrace_getaluop2(child, insn);
-                       break;
-               case 0x01e0f000:
-                       alt = ~ptrace_getaluop2(child, insn);
+       case 0x02000000: {
+               /*
+                * data processing
+                */
+               long aluop1, aluop2, ccbit;
+
+               if ((insn & 0xf000) != 0xf000)
                        break;
+
+               aluop1 = ptrace_getrn(child, insn);
+               aluop2 = ptrace_getaluop2(child, insn);
+               ccbit  = get_stack_long(child, REG_PSR) & CC_C_BIT ? 1 : 0;
+
+               switch (insn & 0x01e00000) {
+               case 0x00000000: alt = aluop1 & aluop2;         break;
+               case 0x00200000: alt = aluop1 ^ aluop2;         break;
+               case 0x00400000: alt = aluop1 - aluop2;         break;
+               case 0x00600000: alt = aluop2 - aluop1;         break;
+               case 0x00800000: alt = aluop1 + aluop2;         break;
+               case 0x00a00000: alt = aluop1 + aluop2 + ccbit; break;
+               case 0x00c00000: alt = aluop1 - aluop2 + ccbit; break;
+               case 0x00e00000: alt = aluop2 - aluop1 + ccbit; break;
+               case 0x01800000: alt = aluop1 | aluop2;         break;
+               case 0x01a00000: alt = aluop2;                  break;
+               case 0x01c00000: alt = aluop1 & ~aluop2;        break;
+               case 0x01e00000: alt = ~aluop2;                 break;
                }
                break;
+       }
+
+       case 0x04000000:
+       case 0x06000000:
+               /*
+                * ldr
+                */
+               if ((insn & 0x0010f000) == 0x0010f000) {
+                       unsigned long base;
 
-       case 0x04100000: /* ldr */
-               if ((insn & 0xf000) == 0xf000) {
-printk ("ldr ");
-                       alt = ptrace_getrn(child, insn);
+                       base = ptrace_getrn(child, insn);
                        if (insn & 1 << 24) {
-                               if (insn & 1 << 23)
-                                       alt += ptrace_getldrop2 (child, insn);
+                               long aluop2;
+
+                               if (insn & 0x02000000)
+                                       aluop2 = ptrace_getldrop2(child, insn);
                                else
-                                       alt -= ptrace_getldrop2 (child, insn);
-                       }
-                       if (read_long (child, alt, &alt) < 0)
-                               alt = 0; /* not valid */
-                       else
-                               alt = pc_pointer (alt);
-               }
-               break;
+                                       aluop2 = insn & 0xfff;
 
-       case 0x06100000: /* ldr imm */
-               if ((insn & 0xf000) == 0xf000) {
-printk ("ldrimm ");
-                       alt = ptrace_getrn(child, insn);
-                       if (insn & 1 << 24) {
                                if (insn & 1 << 23)
-                                       alt += insn & 0xfff;
+                                       base += aluop2;
                                else
-                                       alt -= insn & 0xfff;
+                                       base -= aluop2;
                        }
-                       if (read_long (child, alt, &alt) < 0)
-                               alt = 0; /* not valid */
-                       else
-                               alt = pc_pointer (alt);
+                       if (read_tsk_long(child, base, &alt) == 0)
+                               alt = pc_pointer(alt);
                }
                break;
 
-       case 0x08100000: /* ldm */
-               if (insn & (1 << 15)) {
+       case 0x08000000:
+               /*
+                * ldm
+                */
+               if ((insn & 0x00108000) == 0x00108000) {
                        unsigned long base;
-                       int nr_regs;
-printk ("ldm ");
+                       unsigned int nr_regs;
 
                        if (insn & (1 << 23)) {
                                nr_regs = insn & 65535;
@@ -278,23 +257,22 @@ printk ("ldm ");
                                        nr_regs = 0;
                        }
 
-                       base = ptrace_getrn (child, insn);
+                       base = ptrace_getrn(child, insn);
 
-                       if (read_long (child, base + nr_regs, &alt) < 0)
-                               alt = 0; /* not valid */
-                       else
+                       if (read_tsk_long(child, base + nr_regs, &alt) == 0)
                                alt = pc_pointer (alt);
                        break;
                }
                break;
 
-       case 0x0a000000:
-       case 0x0a100000: { /* bl or b */
+       case 0x0a000000: {
+               /*
+                * bl or b
+                */
                signed long displ;
-printk ("b/bl ");
                /* It's a branch/branch link: instead of trying to
                 * figure out whether the branch will be taken or not,
-                * we'll put a breakpoint at either location.  This is
+                * we'll put a breakpoint at both locations.  This is
                 * simpler, more reliable, and probably not a whole lot
                 * slower than the alternative approach of emulating the
                 * branch.
@@ -306,7 +284,6 @@ printk ("b/bl ");
            }
            break;
        }
-printk ("=%08lX\n", alt);
 
        return alt;
 }
@@ -318,9 +295,9 @@ add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long
        int res = -EINVAL;
 
        if (nr < 2) {
-               res = read_long(child, addr, &dbg->bp[nr].insn);
+               res = read_tsk_long(child, addr, &dbg->bp[nr].insn);
                if (res == 0)
-                       res = write_long(child, addr, BREAKINST);
+                       res = write_tsk_long(child, addr, BREAKINST);
 
                if (res == 0) {
                        dbg->bp[nr].address = addr;
@@ -332,257 +309,309 @@ add_breakpoint(struct task_struct *child, struct debug_info *dbg, unsigned long
        return res;
 }
 
-int ptrace_set_bpt (struct task_struct *child)
+int ptrace_set_bpt(struct task_struct *child)
 {
-       struct debug_info *dbg = &child->thread.debug;
-       unsigned long insn, pc, alt;
+       unsigned long insn, pc;
        int res;
 
-       pc = pc_pointer (get_stack_long (child, 15/*REG_PC*/));
+       pc = pc_pointer(get_stack_long(child, REG_PC));
 
-       res = read_long(child, pc, &insn);
-       if (res >= 0) {
-               res = 0;
+       res = read_tsk_long(child, pc, &insn);
+       if (!res) {
+               struct debug_info *dbg = &child->thread.debug;
+               unsigned long alt;
 
                dbg->nsaved = 0;
 
-               res = add_breakpoint(child, dbg, pc + 4);
+               alt = get_branch_address(child, pc, insn);
+               if (alt)
+                       res = add_breakpoint(child, dbg, alt);
 
-               if (res == 0) {
-                       alt = get_branch_address(child, pc, insn);
-                       if (alt)
-                               res = add_breakpoint(child, dbg, alt);
-               }
+               if (!res && (!alt || predicate(insn) != PREDICATE_ALWAYS))
+                       res = add_breakpoint(child, dbg, pc + 4);
        }
 
        return res;
 }
 
-/* Ensure no single-step breakpoint is pending.  Returns non-zero
+/*
+ * Ensure no single-step breakpoint is pending.  Returns non-zero
  * value if child was being single-stepped.
  */
-int ptrace_cancel_bpt (struct task_struct *child)
+void __ptrace_cancel_bpt(struct task_struct *child)
 {
        struct debug_info *dbg = &child->thread.debug;
-       unsigned long tmp;
        int i, nsaved = dbg->nsaved;
 
        dbg->nsaved = 0;
 
        if (nsaved > 2) {
-               printk ("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
+               printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
                nsaved = 2;
        }
 
        for (i = 0; i < nsaved; i++) {
-               read_long(child, dbg->bp[i].address, &tmp);
+               unsigned long tmp;
+
+               read_tsk_long(child, dbg->bp[i].address, &tmp);
                if (tmp != BREAKINST)
                        printk(KERN_ERR "ptrace_cancel_bpt: weirdness\n");
-               write_long(child, dbg->bp[i].address, dbg->bp[i].insn);
+               write_tsk_long(child, dbg->bp[i].address, dbg->bp[i].insn);
        }
-
-       return nsaved != 0;
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+static int do_ptrace(int request, struct task_struct *child, long addr, long data)
 {
-       struct task_struct *child;
+       unsigned long tmp;
        int ret;
 
-       lock_kernel();
-       ret = -EPERM;
-       if (request == PTRACE_TRACEME) {
-               /* are we already being traced? */
-               if (current->ptrace & PT_PTRACED)
-                       goto out;
-               /* set the ptrace bit in the process flags. */
-               current->ptrace |= PT_PTRACED;
-               ret = 0;
-               goto out;
-       }
-       if (pid == 1)           /* you may not mess with init */
-               goto out;
-       ret = -ESRCH;
-       if (!(child = find_task_by_pid(pid)))
-               goto out;
-       ret = -EPERM;
-       if (request == PTRACE_ATTACH) {
-               if (child == current)
-                       goto out;
-               if ((!child->dumpable ||
-                   (current->uid != child->euid) ||
-                   (current->uid != child->suid) ||
-                   (current->uid != child->uid) ||
-                   (current->gid != child->egid) ||
-                   (current->gid != child->sgid) ||
-                   (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
-                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
-                       goto out;
-               /* the same process cannot be attached many times */
-               if (child->ptrace & PT_PTRACED)
-                       goto out;
-               child->ptrace |= PT_PTRACED;
-               if (child->p_pptr != current) {
-                       REMOVE_LINKS(child);
-                       child->p_pptr = current;
-                       SET_LINKS(child);
-               }
-               send_sig(SIGSTOP, child, 1);
-               ret = 0;
-               goto out;
-       }
-       ret = -ESRCH;
-       if (!(child->ptrace & PT_PTRACED))
-               goto out;
-       if (child->state != TASK_STOPPED) {
-               if (request != PTRACE_KILL)
-                       goto out;
-       }
-       if (child->p_pptr != current)
-               goto out;
-
        switch (request) {
-               case PTRACE_PEEKTEXT:                           /* read word at location addr. */
-               case PTRACE_PEEKDATA: {
-                       unsigned long tmp;
-
-                       ret = read_long(child, addr, &tmp);
+               /*
+                * read word at location "addr" in the child process.
+                */
+               case PTRACE_PEEKTEXT:
+               case PTRACE_PEEKDATA:
+                       ret = read_tsk_long(child, addr, &tmp);
                        if (!ret)
                                ret = put_user(tmp, (unsigned long *) data);
-                       goto out;
-               }
-
-               case PTRACE_PEEKUSR: {                          /* read the word at location addr in the USER area. */
-                       unsigned long tmp;
+                       break;
 
+               /*
+                * read the word at location "addr" in the user registers.
+                */
+               case PTRACE_PEEKUSR:
                        ret = -EIO;
                        if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
-                               goto out;
+                               break;
 
                        tmp = 0;  /* Default return condition */
-                       if (addr < sizeof (struct pt_regs))
+                       if (addr < sizeof(struct pt_regs))
                                tmp = get_stack_long(child, (int)addr >> 2);
                        ret = put_user(tmp, (unsigned long *)data);
-                       goto out;
-               }
+                       break;
 
-               case PTRACE_POKETEXT:                           /* write the word at location addr. */
+               /*
+                * write the word at location addr.
+                */
+               case PTRACE_POKETEXT:
                case PTRACE_POKEDATA:
-                       ret = write_long(child, addr, data);
-                       goto out;
+                       ret = write_tsk_long(child, addr, data);
+                       break;
 
-               case PTRACE_POKEUSR:                            /* write the word at location addr in the USER area */
+               /*
+                * write the word at location addr in the user registers.
+                */
+               case PTRACE_POKEUSR:
                        ret = -EIO;
                        if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
-                               goto out;
+                               break;
 
                        if (addr < sizeof (struct pt_regs))
                                ret = put_stack_long(child, (int)addr >> 2, data);
-                       goto out;
+                       break;
 
-               case PTRACE_SYSCALL:                            /* continue and stop at next (return from) syscall */
-               case PTRACE_CONT:                               /* restart after signal. */
+               /*
+                * continue/restart and stop at next (return from) syscall
+                */
+               case PTRACE_SYSCALL:
+               case PTRACE_CONT:
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
-                               goto out;
+                               break;
                        if (request == PTRACE_SYSCALL)
                                child->ptrace |= PT_TRACESYS;
                        else
                                child->ptrace &= ~PT_TRACESYS;
                        child->exit_code = data;
-                       wake_up_process (child);
                        /* make sure single-step breakpoint is gone. */
-                       ptrace_cancel_bpt (child);
+                       __ptrace_cancel_bpt(child);
+                       wake_up_process(child);
                        ret = 0;
-                       goto out;
+                       break;
 
-               /* make the child exit.  Best I can do is send it a sigkill.
+               /*
+                * make the child exit.  Best I can do is send it a sigkill.
                 * perhaps it should be put in the status that it wants to
                 * exit.
                 */
                case PTRACE_KILL:
-                       if (child->state == TASK_ZOMBIE)        /* already dead */
-                               return 0;
-                       wake_up_process (child);
+                       /* already dead */
+                       ret = 0;
+                       if (child->state == TASK_ZOMBIE)
+                               break;
                        child->exit_code = SIGKILL;
                        /* make sure single-step breakpoint is gone. */
-                       ptrace_cancel_bpt (child);
+                       __ptrace_cancel_bpt(child);
+                       wake_up_process(child);
                        ret = 0;
-                       goto out;
+                       break;
 
-               case PTRACE_SINGLESTEP:                         /* execute single instruction. */
+               /*
+                * execute single instruction.
+                */
+               case PTRACE_SINGLESTEP:
                        ret = -EIO;
                        if ((unsigned long) data > _NSIG)
-                               goto out;
+                               break;
                        child->thread.debug.nsaved = -1;
                        child->ptrace &= ~PT_TRACESYS;
-                       wake_up_process(child);
                        child->exit_code = data;
                        /* give it a chance to run. */
+                       wake_up_process(child);
                        ret = 0;
-                       goto out;
-                       
-               case PTRACE_GETREGS:
-               {       /* Get all gp regs from the child. */
-                       unsigned char *stack;
+                       break;
+
+               /*
+                * detach a process that was attached.
+                */
+               case PTRACE_DETACH:
+                       ret = -EIO;
+                       if ((unsigned long) data > _NSIG)
+                               break;
+                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+                       child->exit_code = data;
+                       write_lock_irq(&tasklist_lock);
+                       REMOVE_LINKS(child);
+                       child->p_pptr = child->p_opptr;
+                       SET_LINKS(child);
+                       write_unlock_irq(&tasklist_lock);
+                       /* make sure single-step breakpoint is gone. */
+                       __ptrace_cancel_bpt(child);
+                       wake_up_process (child);
+                       ret = 0;
+                       break;
+
+               /*
+                * Get all gp regs from the child.
+                */
+               case PTRACE_GETREGS: {
+                       struct pt_regs *regs = get_user_regs(child);
 
                        ret = 0;
-                       stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs));
-                       if (copy_to_user((void *)data, stack,
+                       if (copy_to_user((void *)data, regs,
                                         sizeof(struct pt_regs)))
                                ret = -EFAULT;
 
-                       goto out;
-               };
+                       break;
+               }
 
-               case PTRACE_SETREGS:
-               {
-                       /* Set all gp regs in the child. */
-                       unsigned char *stack;
+               /*
+                * Set all gp regs in the child.
+                */
+               case PTRACE_SETREGS: {
+                       struct pt_regs *regs = get_user_regs(child);
 
                        ret = 0;
-                       stack = (unsigned char *)((unsigned long)child + 8192 - sizeof(struct pt_regs));
-                       if (copy_from_user(stack, (void *)data,
+                       if (copy_from_user(regs, (void *)data,
                                           sizeof(struct pt_regs)))
                                ret = -EFAULT;
-                       goto out;
-                 };
+                       break;
+               }
 
-               case PTRACE_GETFPREGS: 
-                       /* Get the child FPU state. */
-                       ret = 0;
-                       if (copy_to_user((void *)data, &child->thread.fpstate,
-                                        sizeof(struct user_fp)))
-                               ret = -EFAULT;
-                       goto out;
+               /*
+                * Get the child FPU state.
+                */
+               case PTRACE_GETFPREGS:
+                       ret = -EIO;
+                       if (!access_ok(VERIFY_WRITE, (void *)data, sizeof(struct user_fp)))
+                               break;
+
+                       /* we should check child->used_math here */
+                       ret = __copy_to_user((void *)data, &child->thread.fpstate,
+                                            sizeof(struct user_fp)) ? -EFAULT : 0;
+                       break;
                
+               /*
+                * Set the child FPU state.
+                */
                case PTRACE_SETFPREGS:
-                       /* Set the child FPU state. */
-                       ret = 0;
-                       if (copy_from_user(&child->thread.fpstate, (void *)data,
-                                          sizeof(struct user_fp)))
-                               ret = -EFAULT;
-                       goto out;
-
-               case PTRACE_DETACH:                             /* detach a process that was attached. */
                        ret = -EIO;
-                       if ((unsigned long) data > _NSIG)
-                               goto out;
-                       child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-                       wake_up_process (child);
-                       child->exit_code = data;
-                       REMOVE_LINKS(child);
-                       child->p_pptr = child->p_opptr;
-                       SET_LINKS(child);
-                       /* make sure single-step breakpoint is gone. */
-                       ptrace_cancel_bpt (child);
-                       ret = 0;
-                       goto out;
+                       if (!access_ok(VERIFY_READ, (void *)data, sizeof(struct user_fp)))
+                               break;
+
+                       child->used_math = 1;
+                       ret = __copy_from_user(&child->thread.fpstate, (void *)data,
+                                          sizeof(struct user_fp)) ? -EFAULT : 0;
+                       break;
 
                default:
                        ret = -EIO;
+                       break;
+       }
+
+       return ret;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+       struct task_struct *child;
+       int ret;
+
+       lock_kernel();
+       ret = -EPERM;
+       if (request == PTRACE_TRACEME) {
+               /* are we already being traced? */
+               if (current->ptrace & PT_PTRACED)
                        goto out;
+               /* set the ptrace bit in the process flags. */
+               current->ptrace |= PT_PTRACED;
+               ret = 0;
+               goto out;
        }
+       ret = -ESRCH;
+       read_lock(&tasklist_lock);
+       child = find_task_by_pid(pid);
+       if (child)
+               get_task_struct(child);
+       read_unlock(&tasklist_lock);
+       if (!child)
+               goto out;
+
+       ret = -EPERM;
+       if (pid == 1)           /* you may not mess with init */
+               goto out_tsk;
+
+       if (request == PTRACE_ATTACH) {
+               if (child == current)
+                       goto out_tsk;
+               if ((!child->dumpable ||
+                   (current->uid != child->euid) ||
+                   (current->uid != child->suid) ||
+                   (current->uid != child->uid) ||
+                   (current->gid != child->egid) ||
+                   (current->gid != child->sgid) ||
+                   (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+                       goto out_tsk;
+               /* the same process cannot be attached many times */
+               if (child->ptrace & PT_PTRACED)
+                       goto out_tsk;
+               child->ptrace |= PT_PTRACED;
+
+               write_lock_irq(&tasklist_lock);
+               if (child->p_pptr != current) {
+                       REMOVE_LINKS(child);
+                       child->p_pptr = current;
+                       SET_LINKS(child);
+               }
+               write_unlock_irq(&tasklist_lock);
+
+               send_sig(SIGSTOP, child, 1);
+               ret = 0;
+               goto out_tsk;
+       }
+       ret = -ESRCH;
+       if (!(child->ptrace & PT_PTRACED))
+               goto out_tsk;
+       if (child->state != TASK_STOPPED && request != PTRACE_KILL)
+               goto out_tsk;
+       if (child->p_pptr != current)
+               goto out_tsk;
+
+       ret = do_ptrace(request, child, addr, data);
+
+out_tsk:
+       free_task_struct(child);
 out:
        unlock_kernel();
        return ret;
diff --git a/arch/arm/kernel/ptrace.h b/arch/arm/kernel/ptrace.h
new file mode 100644 (file)
index 0000000..feae0ac
--- /dev/null
@@ -0,0 +1,16 @@
+extern void __ptrace_cancel_bpt(struct task_struct *);
+extern int ptrace_set_bpt(struct task_struct *);
+
+/*
+ * Clear a breakpoint, if one exists.
+ */
+static inline int ptrace_cancel_bpt(struct task_struct *tsk)
+{
+       int nsaved = tsk->thread.debug.nsaved;
+
+       if (nsaved)
+               __ptrace_cancel_bpt(tsk);
+
+       return nsaved;
+}
+
index 93a370f2dcfa3bce7c8724d3074163b0f7e86fe3..8118b6a683165c34b6b7b57105d6f8dab36a4092 100644 (file)
@@ -8,7 +8,6 @@
  * Modified for ARM by Russell King
  */
 #include <linux/sched.h>
-#include <linux/errno.h>
 
 #include <asm/semaphore.h>
 
index 1f42955408379623bc9a84b07ae8eb5b0584cf93..c6010476a8f266bb92ec261532f631c2addc4316 100644 (file)
@@ -35,6 +35,7 @@ extern void paging_init(struct meminfo *);
 extern void bootmem_init(struct meminfo *);
 extern void reboot_setup(char *str);
 extern void disable_hlt(void);
+extern unsigned long memparse(char *ptr, char **retptr);
 extern int root_mountflags;
 extern int _stext, _text, _etext, _edata, _end;
 
index 431dd96c1153c5e23dd353e807889fd276c76946..3e6cf6cb441a5b03104f2fd275d236857e6bc049 100644 (file)
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
-#include <linux/signal.h>
 #include <linux/errno.h>
+#include <linux/signal.h>
 #include <linux/wait.h>
 #include <linux/ptrace.h>
-#include <linux/unistd.h>
 #include <linux/stddef.h>
-#include <linux/binfmts.h>
+#include <linux/unistd.h>
 #include <linux/tty.h>
 
+#include <asm/pgalloc.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
-#include <asm/pgalloc.h>
+
+#include "ptrace.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -31,8 +32,6 @@
 asmlinkage int sys_wait4(pid_t pid, unsigned long * stat_addr,
                         int options, unsigned long *ru);
 asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
-extern int ptrace_cancel_bpt (struct task_struct *);
-extern int ptrace_set_bpt (struct task_struct *);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
@@ -234,7 +233,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        /* Send SIGTRAP if we're single-stepping */
-       if (ptrace_cancel_bpt (current))
+       if (ptrace_cancel_bpt(current))
                send_sig(SIGTRAP, current, 1);
 
        return regs->ARM_r0;
@@ -274,7 +273,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        /* Send SIGTRAP if we're single-stepping */
-       if (ptrace_cancel_bpt (current))
+       if (ptrace_cancel_bpt(current))
                send_sig(SIGTRAP, current, 1);
 
        return regs->ARM_r0;
@@ -500,7 +499,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
        if (!oldset)
                oldset = &current->blocked;
 
-       single_stepping = ptrace_cancel_bpt (current);
+       single_stepping = ptrace_cancel_bpt(current);
 
        for (;;) {
                unsigned long signr;
@@ -518,7 +517,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                        current->state = TASK_STOPPED;
                        notify_parent(current, SIGCHLD);
                        schedule();
-                       single_stepping |= ptrace_cancel_bpt (current);
+                       single_stepping |= ptrace_cancel_bpt(current);
 
                        /* We're back.  Did the debugger cancel the sig?  */
                        if (!(signr = current->exit_code))
@@ -617,7 +616,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                /* Whee!  Actually deliver the signal.  */
                handle_signal(signr, ka, &info, oldset, regs);
                if (single_stepping)
-                       ptrace_set_bpt (current);
+                       ptrace_set_bpt(current);
                return 1;
        }
 
@@ -629,6 +628,6 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
                regs->ARM_pc -= 4;
        }
        if (single_stepping)
-               ptrace_set_bpt (current);
+               ptrace_set_bpt(current);
        return 0;
 }
index bdb725551dedeb9af42600c252126212bddff015..d7f6640eb555e4ca47fed235759a190a4242f34a 100644 (file)
@@ -13,7 +13,6 @@
  *             "A Kernel Model for Precision Timekeeping" by Dave Mills
  */
 #include <linux/config.h>
-#include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
index 1d692dd3503d74ec579059dd7d7fe377cebe0ab6..188f89722743441ff598f104e8539407e46e8078 100644 (file)
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
+#include <linux/ptrace.h>
 #include <linux/init.h>
 
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
 #include <asm/atomic.h>
+#include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "ptrace.h"
 
 extern void c_backtrace (unsigned long fp, int pmode);
-extern int ptrace_cancel_bpt (struct task_struct *);
 
 char *processor_modes[]=
 { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -46,8 +48,6 @@ static inline void console_verbose(void)
        console_loglevel = 15;
 }
 
-int kstack_depth_to_print = 200;
-
 /*
  * Stack pointers should always be within the kernels view of
  * physical memory.  If it is not there, then we can't dump
@@ -199,37 +199,48 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
        die(str, regs, err);
 }
 
-void bad_user_access_alignment(const void *ptr)
-{
-       printk(KERN_ERR "bad user access alignment: ptr = %p, pc = %p\n", ptr, 
-               __builtin_return_address(0));
-       current->thread.error_code = 0;
-       current->thread.trap_no = 11;
-       force_sig(SIGBUS, current);
-/*     die_if_kernel("Oops - bad user access alignment", regs, mode);*/
-}
-
 asmlinkage void do_undefinstr(int address, struct pt_regs *regs, int mode)
 {
+       unsigned long addr = instruction_pointer(regs);
+       siginfo_t info;
+
 #ifdef CONFIG_DEBUG_USER
        printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n",
-               current->comm, current->pid, instruction_pointer(regs));
+               current->comm, current->pid, addr);
 #endif
+
        current->thread.error_code = 0;
        current->thread.trap_no = 6;
-       force_sig(SIGILL, current);
+
+       info.si_signo = SIGILL;
+       info.si_errno = 0;
+       info.si_code  = ILL_ILLOPC;
+       info.si_addr  = (void *)addr;
+
+       force_sig_info(SIGILL, &info, current);
+
        die_if_kernel("Oops - undefined instruction", regs, mode);
 }
 
 asmlinkage void do_excpt(int address, struct pt_regs *regs, int mode)
 {
+       siginfo_t info;
+
 #ifdef CONFIG_DEBUG_USER
        printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n",
                current->comm, current->pid, instruction_pointer(regs));
 #endif
+
        current->thread.error_code = 0;
        current->thread.trap_no = 11;
-       force_sig(SIGBUS, current);
+
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code  = BUS_ADRERR;
+       info.si_addr  = (void *)address;
+
+       force_sig_info(SIGBUS, &info, current);
+
        die_if_kernel("Oops - address exception", regs, mode);
 }
 
@@ -268,33 +279,39 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, int proc_mode)
        while(1);
 }
 
-/*
- * 'math_state_restore()' saves the current math information in the
- * old math state array, and gets the new ones from the current task.
- *
- * We no longer save/restore the math state on every context switch
- * any more.  We only do this now if it actually gets used.
- */
-asmlinkage void math_state_restore (void)
-{
-       current->used_math = 1;
-}
-
 /*
  * Handle some more esoteric system calls
  */
-asmlinkage int arm_syscall (int no, struct pt_regs *regs)
+asmlinkage int arm_syscall(int no, struct pt_regs *regs)
 {
+       siginfo_t info;
+
        switch (no) {
        case 0: /* branch through 0 */
-               force_sig(SIGSEGV, current);
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               info.si_code  = SEGV_MAPERR;
+               info.si_addr  = NULL;
+
+               force_sig_info(SIGSEGV, &info, current);
+
                die_if_kernel("branch through zero", regs, 0);
                break;
 
-       case 1: /* SWI_BREAK_POINT */
-               regs->ARM_pc -= 4; /* Decrement PC by one instruction */
-               ptrace_cancel_bpt(current);
-               force_sig(SIGTRAP, current);
+       case 1: /* SWI BREAK_POINT */
+               /*
+                * The PC is always left pointing at the next
+                * instruction.  Fix this.
+                */
+               regs->ARM_pc -= 4;
+               __ptrace_cancel_bpt(current);
+
+               info.si_signo = SIGTRAP;
+               info.si_errno = 0;
+               info.si_code  = TRAP_BRKPT;
+               info.si_addr  = (void *)instruction_pointer(regs);
+
+               force_sig_info(SIGTRAP, &info, current);
                return regs->ARM_r0;
 
        case 2: /* sys_cacheflush */
@@ -350,29 +367,24 @@ asmlinkage void deferred(int n, struct pt_regs *regs)
        die_if_kernel("Oops", regs, n);
 }
 
-asmlinkage void arm_malalignedptr(const char *str, void *pc, volatile void *ptr)
-{
-       printk("Mal-aligned pointer in %s: %p (PC=%p)\n", str, ptr, pc);
-}
-
-asmlinkage void arm_invalidptr(const char *function, int size)
+void __bad_xchg(volatile void *ptr, int size)
 {
-       printk("Invalid pointer size in %s (pc=%p) size %d\n",
-               function, __builtin_return_address(0), size);
+       printk("xchg: bad data size: pc 0x%p, ptr 0x%p, size %d\n",
+               __builtin_return_address(0), ptr, size);
+       BUG();
 }
 
 /*
- * A data abort trap was taken, but the instruction was not an instruction
- * which should cause the trap to be taken.  Try to abort it.  Note that
- * the while(1) is there because we cannot currently handle returning from
- * this function.
+ * A data abort trap was taken, but we did not handle the instruction.
+ * Try to abort the user program, or panic if it was the kernel.
  */
 asmlinkage void
 baddataabort(int code, unsigned long instr, struct pt_regs *regs)
 {
        unsigned long addr = instruction_pointer(regs);
+       siginfo_t info;
 
-#ifdef CONFIG_DEBUG_ERRORS
+#ifdef CONFIG_DEBUG_USER
        dump_instr(addr, 1);
        {
                pgd_t *pgd;
@@ -389,16 +401,22 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
                printk ("\n");
        }
 #endif
-       force_sig(SIGILL, current);
+
+       info.si_signo = SIGILL;
+       info.si_errno = 0;
+       info.si_code  = ILL_ILLOPC;
+       info.si_addr  = (void *)addr;
+
+       force_sig_info(SIGILL, &info, current);
        die_if_kernel("unknown data abort code", regs, instr);
-       while (1);
 }
 
 void __bug(const char *file, int line, void *data)
 {
-       printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
+       printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
        if (data)
-               printk(KERN_CRIT"extra data = %p\n", data);
+               printk(KERN_CRIT" - extra data = %p", data);
+       printk("\n");
        BUG();
 }
 
index 3859377088b53e8f6d4c4eb228f8d8004c05848e..519f1965ac7beb4e7b93b741782a2dccbddfda51 100644 (file)
@@ -187,6 +187,7 @@ static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
                tsk->thread.error_code = mode;
                tsk->thread.trap_no = 14;
                si.si_signo = SIGSEGV;
+               si.si_errno = 0;
                si.si_code = fault == -1 ? SEGV_ACCERR : SEGV_MAPERR;
                si.si_addr = (void *)addr;
                force_sig_info(SIGSEGV, &si, tsk);
index 34bd513667d6937387826383e26beb1a82f6852a..1edbc35fd938924a48687da67ecd16eac24c00b1 100644 (file)
@@ -410,9 +410,24 @@ void __init pagetable_init(struct meminfo *mi)
        flush_cache_all();
 }
 
-/*
- * The mem_map array can get very big.  Free the unused area of the memory map.
- */
+static inline void free_memmap(unsigned long start, unsigned long end)
+{
+       unsigned long pg, pgend;
+
+       start = __phys_to_virt(start);
+       end   = __phys_to_virt(end);
+
+       pg    = PAGE_ALIGN((unsigned long)(mem_map + MAP_NR(start)));
+       pgend = ((unsigned long)(mem_map + MAP_NR(end))) & PAGE_MASK;
+
+       start = __virt_to_phys(pg);
+       end   = __virt_to_phys(pgend);
+       /*
+        * The mem_map is always stored in node 0
+        */
+       free_bootmem_node(0, start, end - start);
+}
+
 static inline void free_unused_memmap_node(int node, struct meminfo *mi)
 {
        unsigned long bank_start, prev_bank_end = 0;
@@ -434,14 +449,17 @@ static inline void free_unused_memmap_node(int node, struct meminfo *mi)
                 * between the current bank and the previous, free it.
                 */
                if (prev_bank_end && prev_bank_end != bank_start)
-                       free_bootmem_node(node, prev_bank_end,
-                                         bank_start - prev_bank_end);
+                       free_memmap(prev_bank_end, bank_start);
 
                prev_bank_end = PAGE_ALIGN(mi->bank[i].start +
                                           mi->bank[i].size);
        }
 }
 
+/*
+ * The mem_map array can get very big.  Free
+ * the unused area of the memory map.
+ */
 void __init create_memmap_holes(struct meminfo *mi)
 {
        int node;
index 36a9d8b28fcaa8962d4d81d79611c5178f44028a..6dd48c91947786fa654d7b6adf72bb607e4da45b 100644 (file)
@@ -286,7 +286,6 @@ SYMBOL_NAME(arm2_processor_functions):
                .word   _arm2_proc_fin
                .word   _arm2_set_pgd
                .word   _arm2_xchg_1
-               .word   SYMBOL_NAME(abort)
                .word   _arm2_xchg_4
 
 cpu_arm2_info:
@@ -300,7 +299,6 @@ SYMBOL_NAME(arm250_processor_functions):
                .word   _arm2_proc_fin
                .word   _arm2_set_pgd
                .word   _arm3_xchg_1
-               .word   SYMBOL_NAME(abort)
                .word   _arm3_xchg_4
 
 cpu_arm250_info:
@@ -314,7 +312,6 @@ SYMBOL_NAME(arm3_processor_functions):
                .word   _arm3_proc_fin
                .word   _arm3_set_pgd
                .word   _arm3_xchg_1
-               .word   SYMBOL_NAME(abort)
                .word   _arm3_xchg_4
 
 cpu_arm3_info:
index 5d7605b851ba1c5b36cabbd89b05b6bad3c6ae43..b18d69d987d9b17ceac0fcb8fba5fb00e2b577c9 100644 (file)
@@ -158,8 +158,8 @@ Ldata_unknown:      @ Part of jumptable
                mov     r0, r2
                mov     r1, r4
                mov     r2, r3
-               b       baddataabort
-
+               bl      baddataabort
+               b       ret_from_sys_call
 
 Ldata_lateldrpreconst:
                tst     r4, #1 << 21                    @ check writeback bit
index 738ff9a434079e3e02e7b96c19c858adb1c9fa64..d4919662520fb0787fc0c8f2aa62ec2e92eaeb8e 100644 (file)
@@ -146,8 +146,8 @@ Ldata_unknown:      @ Part of jumptable
                mov     r0, r2
                mov     r1, r4
                mov     r2, r3
-               b       baddataabort
-
+               bl      baddataabort
+               b       ret_from_sys_call
 
 Ldata_lateldrpreconst:
                tst     r4, #1 << 21                    @ check writeback bit
index 933d6c3c9894bc00a5584631401557e216443567..b98bf47489d4fae1f8e66e71439b0c03e0bc1073 100644 (file)
@@ -464,7 +464,7 @@ void __init pcibios_fixup_irqs(void)
        }
 }
 
-void __init pcibios_penalize_isa_irq(int irq)
+void pcibios_penalize_isa_irq(int irq)
 {
        /*
         *  If any ISAPnP device reports an IRQ in its list of possible
index 05ed9d932be932710a01897072cad853612cde09..82d3027aa9f30a6b2fd09e7a50b65bc83f525205 100644 (file)
@@ -215,7 +215,6 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len,
                        goto out;
        }
 
-       down(&current->mm->mmap_sem);
        lock_kernel();
        retval = -EINVAL;
        len = PAGE_ALIGN(len);
@@ -230,11 +229,12 @@ static unsigned long do_mmap2(unsigned long addr, unsigned long len,
                goto out_putf;
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       down(&current->mm->mmap_sem);
        retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+       up(&current->mm->mmap_sem);
 
 out_putf:
        unlock_kernel();
-       up(&current->mm->mmap_sem);
        if (file)
                fput(file);
 out:
index 1c3dfe6e2c7b6c62cf2beca6e428215e018d5f23..f64563cab3371c49810647c3fda57920b5e9ba66 100644 (file)
@@ -68,7 +68,6 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
        struct file * file = NULL;
        unsigned long retval, ret_type;
 
-       down(&current->mm->mmap_sem);
        lock_kernel();
        if(flags & MAP_NORESERVE) {
                static int cnt;
@@ -118,7 +117,9 @@ asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
        }
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       down(&current->mm->mmap_sem);
        retval = do_mmap(file, addr, len, prot, flags, off);
+       up(&current->mm->mmap_sem);
        if(!ret_type)
                retval = ((retval < PAGE_OFFSET) ? 0 : retval);
 
@@ -127,7 +128,6 @@ out_putf:
                fput(file);
 out:
        unlock_kernel();
-       up(&current->mm->mmap_sem);
        return retval;
 }
 
index 9e51aadadc2ab542bef620dd1e3046ba6747cd10..2aff3033aa35c5e418f43f3e905c69fd5d6033f7 100644 (file)
@@ -227,7 +227,6 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
        len = PAGE_ALIGN(len);
        retval = -EINVAL;
 
-       down(&current->mm->mmap_sem);
        lock_kernel();
 
        if (current->thread.flags & SPARC_FLAG_32BIT) {
@@ -241,11 +240,12 @@ asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
                        goto out_putf;
        }
 
+       down(&current->mm->mmap_sem);
        retval = do_mmap(file, addr, len, prot, flags, off);
+       up(&current->mm->mmap_sem);
 
 out_putf:
        unlock_kernel();
-       up(&current->mm->mmap_sem);
        if (file)
                fput(file);
 out:
index 26c5faecdebd25113a501473bed0b7914d2229f8..e27892de30d7e2bbeb56317300a2532acf574d12 100644 (file)
@@ -3029,9 +3029,7 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
        memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
 
-       lock_kernel();
        file = open_exec(filename);
-       unlock_kernel();
 
        retval = PTR_ERR(file);
        if (IS_ERR(file))
@@ -3043,10 +3041,12 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
        bprm.loader = 0;
        bprm.exec = 0;
        if ((bprm.argc = count32(argv)) < 0) {
+               allow_write_access(file);
                fput(file);
                return bprm.argc;
        }
        if ((bprm.envc = count32(envp)) < 0) {
+               allow_write_access(file);
                fput(file);
                return bprm.envc;
        }
@@ -3075,6 +3075,7 @@ do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
 
 out:
        /* Something went wrong, return the inode and free the argument pages*/
+       allow_write_access(bprm.file);
        if (bprm.file)
                fput(bprm.file);
 
index b13846fe97088bdf7aa12f9c19aca3334161d685..70adfe21a229216be4fdeaa17da28011b1e7696d 100644 (file)
@@ -68,7 +68,6 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
        struct file *file = NULL;
        unsigned long retval, ret_type;
 
-       down(&current->mm->mmap_sem);
        lock_kernel();
        if(flags & MAP_NORESERVE) {
                static int cnt;
@@ -102,10 +101,12 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 of
        flags &= ~_MAP_NEW;
 
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+       down(&current->mm->mmap_sem);
        retval = do_mmap(file,
                         (unsigned long) addr, (unsigned long) len,
                         (unsigned long) prot, (unsigned long) flags,
                         (unsigned long) off);
+       up(&current->mm->mmap_sem);
        if(!ret_type)
                retval = ((retval < 0xf0000000) ? 0 : retval);
 out_putf:
@@ -113,7 +114,6 @@ out_putf:
                fput(file);
 out:
        unlock_kernel();
-       up(&current->mm->mmap_sem);
        return (u32) retval;
 }
 
index 316af0d4e71b342f776828f6023c594c9ed7ff9d..d4658724ad4b5b6d207a63699815a6023710c17e 100644 (file)
@@ -33,6 +33,7 @@ obj-rpc               := keyb_ps2.o
 obj-$(CONFIG_RPCMOUSE)         += mouse_rpc.o
 obj-$(CONFIG_ATOMWIDE_SERIAL)  += serial-atomwide.o
 obj-$(CONFIG_DUALSP_SERIAL)    += serial-dualsp.o
+obj-$(CONFIG_ARCH_ACORN)       += defkeymap-acorn.o
 
 # Do the i2c and rtc last
 obj-y          += $(obj-$(MACHINE)) i2c.o pcf8583.o
diff --git a/drivers/acorn/char/defkeymap-acorn.c b/drivers/acorn/char/defkeymap-acorn.c
new file mode 100644 (file)
index 0000000..4974cd2
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * linux/arch/arm/drivers/char/defkeymap.c
+ *
+ * Copyright (C) 1995, 1996 Russell King
+ */
+
+#include <linux/types.h>
+#include <linux/keyboard.h>
+#include <linux/kd.h>
+
+/* Normal (maps 1:1 with no processing) */
+#define KTn    0xF0
+/* Function keys */
+#define KTf    0xF1
+/* Special (Performs special house-keeping funcs) */
+#define KTs    0xF2
+#define KIGNORE                K(KTs, 0)       /* Ignore */
+#define KENTER         K(KTs, 1)       /* Enter */
+#define KREGS          K(KTs, 2)       /* Regs */
+#define KMEM           K(KTs, 3)       /* Mem */
+#define KSTAT          K(KTs, 4)       /* State */
+#define KINTR          K(KTs, 5)       /* Intr */
+#define Ksl    6       /* Last console */
+#define KCAPSLK                K(KTs, 7)       /* Caps lock */
+#define KNUMLK         K(KTs, 8)       /* Num-lock */
+#define KSCRLLK                K(KTs, 9)       /* Scroll-lock */
+#define KSCRLFOR       K(KTs,10)       /* Scroll forward */
+#define KSCRLBAK       K(KTs,11)       /* Scroll back */
+#define KREBOOT                K(KTs,12)       /* Reboot */
+#define KCAPSON                K(KTs,13)       /* Caps on */
+#define KCOMPOSE       K(KTs,14)       /* Compose */
+#define KSAK           K(KTs,15)       /* SAK */
+#define CONS_DEC       K(KTs,16)       /* Dec console */
+#define CONS_INC       K(KTs,17)       /* Incr console */
+#define KFLOPPY                K(KTs,18)       /* Floppy */
+/* Key pad (0-9 = digits, 10=+, 11=-, 12=*, 13=/, 14=enter, 16=., 17=# */
+#define KTp    0xF3
+#define KPAD_0         K(KTp, 0 )
+#define KPAD_1         K(KTp, 1 )
+#define KPAD_2         K(KTp, 2 )
+#define KPAD_3         K(KTp, 3 )
+#define KPAD_4         K(KTp, 4 )
+#define KPAD_5         K(KTp, 5 )
+#define KPAD_6         K(KTp, 6 )
+#define KPAD_7         K(KTp, 7 )
+#define KPAD_8         K(KTp, 8 )
+#define KPAD_9         K(KTp, 9 )
+#define KPAD_PL                K(KTp,10 )
+#define KPAD_MI                K(KTp,11 )
+#define KPAD_ML                K(KTp,12 )
+#define KPAD_DV                K(KTp,13 )
+#define KPAD_EN                K(KTp,14 )
+#define KPAD_DT                K(KTp,16 )
+#define KPAD_HS                K(KTp,20 )
+/* Console switching */
+#define KCn    0xF5
+/* Cursor */
+#define KTc    0xF6
+#define Kcd    0       /* Cursor down */
+#define Kcl    1       /* Cursor left */
+#define Kcr    2       /* Cursor right */
+#define Kcu    3       /* Cursor up */
+/* Shift/alt modifiers etc */
+#define KMd    0xF7
+#define KSHIFT         K(KMd, 0 )
+#define KALTGR         K(KMd, 1 )
+#define KCTRL          K(KMd, 2 )
+#define KALT           K(KMd, 3 )
+/* Meta */
+#define KMt    0xF8
+#define KAs    0xF9
+#define KPADA_0                K(KAs, 0 )
+#define KPADA_1                K(KAs, 1 )
+#define KPADA_2                K(KAs, 2 )
+#define KPADA_3                K(KAs, 3 )
+#define KPADA_4                K(KAs, 4 )
+#define KPADA_5                K(KAs, 5 )
+#define KPADA_6                K(KAs, 6 )
+#define KPADA_7                K(KAs, 7 )
+#define KPADA_8                K(KAs, 8 )
+#define KPADA_9                K(KAs, 9 )
+#define KPADB_0                K(KAs,10 )
+#define KPADB_1                K(KAs,11 )
+#define KPADB_2                K(KAs,12 )
+#define KPADB_3                K(KAs,13 )
+#define KPADB_4                K(KAs,14 )
+#define KPADB_5                K(KAs,15 )
+#define KPADB_6                K(KAs,16 )
+#define KPADB_7                K(KAs,17 )
+#define KPADB_8                K(KAs,18 )
+#define KPADB_9                K(KAs,19 )
+/* Locking keys */
+#define KLk    0xFA
+/* Letters */
+#define KTl    0xFB
+
+u_short plain_map[NR_KEYS]=
+{
+  K(KTn, 27),K(KTf,  0),K(KTf,  1),K(KTf,  2 ),K(KTf,  3),K(KTf,  4),K(KTf,  5 ),K(KTf,  6),
+  K(KTf,  7),K(KTf,  8),K(KTf,  9),K(KTf, 10 ),K(KTf, 11),KIGNORE   ,KSCRLLK    ,KINTR     ,
+  K(KTn,'`'),K(KTn,'1'),K(KTn,'2'),K(KTn,'3' ),K(KTn,'4'),K(KTn,'5'),K(KTn,'6' ),K(KTn,'7'),
+  K(KTn,'8'),K(KTn,'9'),K(KTn,'0'),K(KTn,'-' ),K(KTn,'='),K(KTn,'£'),K(KTn,127 ),K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,K(KTn,  9 ),K(KTl,'q'),
+  K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'),
+  K(KTl,'p'),K(KTn,'['),K(KTn,']'),K(KTn,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25  ),KPAD_7    ,
+  KPAD_8    ,KPAD_9    ,KPAD_MI   ,KCTRL      ,K(KTl,'a'),K(KTl,'s'),K(KTl,'d' ),K(KTl,'f'),
+  K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),K(KTn,';'),K(KTn,'\''),KENTER    ,
+  KPAD_4    ,KPAD_5    ,KPAD_6    ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KTl,'z' ),K(KTl,'x'),
+  K(KTl,'c'),K(KTl,'v'),K(KTl,'b'),K(KTl,'n' ),K(KTl,'m'),K(KTn,','),K(KTn,'.' ),K(KTn,'/'),
+  KSHIFT    ,K(KTc,Kcu),KPAD_1    ,KPAD_2     ,KPAD_3    ,KCAPSLK   ,KALT       ,K(KTn,' '),
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0    ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short shift_map[NR_KEYS]=
+{
+  K(KTn, 27),K(KTf, 10),K(KTf, 11),K(KTf, 12 ),K(KTf, 13),K(KTf, 14),K(KTf, 15 ),K(KTf, 16),
+  K(KTf, 17),K(KTf, 18),K(KTf, 19),K(KTf, 20 ),K(KTf, 21),KIGNORE   ,KMEM       ,KINTR     ,
+  K(KTn,'~'),K(KTn,'!'),K(KTn,'@'),K(KTn,'#' ),K(KTn,'$'),K(KTn,'%'),K(KTn,'^' ),K(KTn,'&'),
+  K(KTn,'*'),K(KTn,'('),K(KTn,')'),K(KTn,'_' ),K(KTn,'+'),K(KTn,'¤'),K(KTn,127 ),K(KTf,21 ),
+  K(KTf,20 ),KSCRLBAK  ,KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,K(KTn,  9 ),K(KTl,'Q'),
+  K(KTl,'W'),K(KTl,'E'),K(KTl,'R'),K(KTl,'T' ),K(KTl,'Y'),K(KTl,'U'),K(KTl,'I' ),K(KTl,'O'),
+  K(KTl,'P'),K(KTn,'{'),K(KTn,'}'),K(KTn,'|' ),K(KTf,22 ),K(KTf,23 ),KSCRLFOR   ,KPAD_7    ,
+  KPAD_8    ,KPAD_9    ,KPAD_MI   ,KCTRL      ,K(KTl,'A'),K(KTl,'S'),K(KTl,'D' ),K(KTl,'F'),
+  K(KTl,'G'),K(KTl,'H'),K(KTl,'J'),K(KTl,'K' ),K(KTl,'L'),K(KTn,':'),K(KTn,'"' ),KENTER    ,
+  KPAD_4    ,KPAD_5    ,KPAD_6    ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KTl,'Z' ),K(KTl,'X'),
+  K(KTl,'C'),K(KTl,'V'),K(KTl,'B'),K(KTl,'N' ),K(KTl,'M'),K(KTn,'<'),K(KTn,'>' ),K(KTn,'?'),
+  KSHIFT    ,K(KTc,Kcu),KPAD_1    ,KPAD_2     ,KPAD_3    ,KCAPSLK   ,KALT       ,K(KTn,' '),
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0    ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short altgr_map[NR_KEYS]=
+{
+  KIGNORE   ,K(KCn,12 ),K(KCn,13 ),K(KCn,14  ),K(KCn,15 ),K(KCn,16 ),K(KCn,17  ),K(KCn, 18),
+  K(KCn, 19),K(KCn,20 ),K(KCn,21 ),K(KCn,22  ),K(KCn,23 ),KIGNORE   ,KREGS      ,KINTR     ,
+  KIGNORE   ,KIGNORE   ,K(KTn,'@'),KIGNORE    ,K(KTn,'$'),KIGNORE   ,KIGNORE    ,K(KTn,'{'),
+  K(KTn,'['),K(KTn,']'),K(KTn,'}'),K(KTn,'\\'),KIGNORE   ,KIGNORE   ,KIGNORE    ,K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,KIGNORE    ,K(KTl,'q'),
+  K(KTl,'w'),K(KTl,'e'),K(KTl,'r'),K(KTl,'t' ),K(KTl,'y'),K(KTl,'u'),K(KTl,'i' ),K(KTl,'o'),
+  K(KTl,'p'),KIGNORE   ,K(KTn,'~'),KIGNORE    ,K(KTf,22 ),K(KTf,23 ),K(KTf,25  ),KPADB_7   ,
+  KPADB_8   ,KPADB_9   ,KPAD_MI   ,KCTRL      ,K(KAs,20 ),K(KTl,'s'),K(KAs,23  ),K(KAs,25 ),
+  K(KTl,'g'),K(KTl,'h'),K(KTl,'j'),K(KTl,'k' ),K(KTl,'l'),KIGNORE   ,KIGNORE    ,KENTER    ,
+  KPADB_4   ,KPADB_5   ,KPADB_6   ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KTl,'z' ),K(KTl,'x'),
+  K(KAs,22 ),K(KTl,'v'),K(KTl,21 ),K(KTl,'n' ),K(KTl,'m'),KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KSHIFT    ,K(KTc,Kcu),KPADB_1   ,KPADB_2    ,KPADB_3   ,KCAPSLK   ,KALT       ,KIGNORE   ,
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPADB_0   ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short ctrl_map[NR_KEYS]=
+{
+  KIGNORE   ,K(KTf,  0),K(KTf,  1),K(KTf,  2 ),K(KTf,  3),K(KTf,  4),K(KTf, 5  ),K(KTf,  6),
+  K(KTf,  7),K(KTf,  8),K(KTf,  9),K(KTf, 10 ),K(KTf, 11),KIGNORE   ,KSTAT      ,KINTR     ,
+  KIGNORE   ,K(KTn, 1 ),K(KTn, 2 ),K(KTn, 3  ),K(KTn, 4 ),K(KTn, 5 ),K(KTn, 6  ),K(KTn, 7 ),
+  K(KTn, 8 ),K(KTn, 9 ),K(KTn, 0 ),K(KTn,31  ),KIGNORE   ,KIGNORE   ,K(KTn, 8  ),K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,KIGNORE    ,K(KTn,17 ),
+  K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20  ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9  ),K(KTn,15 ),
+  K(KTn,16 ),K(KTn,27 ),K(KTn,29 ),K(KTn,28  ),K(KTf,22 ),K(KTf,23 ),K(KTf,25  ),KPAD_7    ,
+  KPAD_8    ,KPAD_9    ,KPAD_MI   ,KCTRL      ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4  ),K(KTn, 6 ),
+  K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11  ),K(KTn,12 ),KIGNORE   ,K(KTn, 7  ),KENTER    ,
+  KPAD_4    ,KPAD_5    ,KPAD_6    ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KTn,26  ),K(KTn,24 ),
+  K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14  ),K(KTn,13 ),KIGNORE   ,KCOMPOSE   ,K(KTn,127),
+  KSHIFT    ,K(KTc,Kcu),KPAD_1    ,KPAD_2     ,KPAD_3    ,KCAPSLK   ,KALT       ,K(KTn, 0 ),
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0    ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short shift_ctrl_map[NR_KEYS]=
+{
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KFLOPPY    ,KINTR     ,
+  KIGNORE   ,KIGNORE   ,K(KTn, 0 ),KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,K(KTn,31  ),KIGNORE   ,KIGNORE   ,KIGNORE    ,K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,KIGNORE    ,K(KTn,17 ),
+  K(KTn,23 ),K(KTn, 5 ),K(KTn,18 ),K(KTn,20  ),K(KTn,25 ),K(KTn,21 ),K(KTn, 9  ),K(KTn,15 ),
+  K(KTn,16 ),KIGNORE   ,KIGNORE   ,KIGNORE    ,K(KTf,22 ),K(KTf,23 ),K(KTf,25  ),KPAD_7    ,
+  KPAD_8    ,KPAD_9    ,KPAD_MI   ,KCTRL      ,K(KTn, 1 ),K(KTn,19 ),K(KTn, 4  ),K(KTn, 6 ),
+  K(KTn, 7 ),K(KTn, 8 ),K(KTn,10 ),K(KTn,11  ),K(KTn,12 ),KIGNORE   ,K(KTn, 7  ),KENTER    ,
+  KPAD_4    ,KPAD_5    ,KPAD_6    ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KTn,26  ),K(KTn,24 ),
+  K(KTn, 3 ),K(KTn,22 ),K(KTn, 2 ),K(KTn,14  ),K(KTn,13 ),KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KSHIFT    ,K(KTc,Kcu),KPAD_1    ,KPAD_2     ,KPAD_3    ,KCAPSLK   ,KALT       ,K(KTn, 0 ),
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0    ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short alt_map[NR_KEYS]=
+{
+  K(KMt,27 ),K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2  ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5  ),K(KCn, 6 ),
+  K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10  ),K(KCn,11 ),KIGNORE   ,KSCRLLK    ,KINTR     ,
+  K(KMt,'`'),K(KMt,'1'),K(KMt,'2'),K(KMt,'3' ),K(KMt,'4'),K(KMt,'5'),K(KMt,'6' ),K(KMt,'7'),
+  K(KMt,'8'),K(KMt,'9'),K(KMt,'0'),K(KMt,'-' ),K(KMt,'='),K(KMt,'£'),K(KMt,127 ),K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,K(KMt, 9  ),K(KMt,'q'),
+  K(KMt,'w'),K(KMt,'e'),K(KMt,'r'),K(KMt,'t' ),K(KMt,'y'),K(KMt,'u'),K(KMt,'i' ),K(KMt,'o'),
+  K(KMt,'p'),K(KMt,'['),K(KMt,']'),K(KMt,'\\'),K(KTf,22 ),K(KTf,23 ),K(KTf,25  ),KPADA_7   ,
+  KPADA_8   ,KPADA_9   ,KPAD_MI   ,KCTRL      ,K(KMt,'a'),K(KMt,'s'),K(KMt,'d' ),K(KMt,'f'),
+  K(KMt,'g'),K(KMt,'h'),K(KMt,'j'),K(KMt,'k' ),K(KMt,'l'),K(KMt,';'),K(KMt,'\''),K(KMt,13 ),
+  KPADA_4   ,KPADA_5   ,KPADA_6   ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KMt,'z' ),K(KMt,'x'),
+  K(KMt,'c'),K(KMt,'v'),K(KMt,'b'),K(KMt,'n' ),K(KMt,'m'),K(KMt,','),K(KMt,'.' ),KIGNORE   ,
+  KSHIFT    ,K(KTc,Kcu),KPADA_1   ,KPADA_2    ,KPADA_3   ,KCAPSLK   ,KALT       ,K(KMt,' '),
+  KALTGR    ,KCTRL     ,CONS_DEC  ,K(KTc,Kcd ),CONS_INC  ,KPADA_0   ,KPAD_DT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+u_short ctrl_alt_map[NR_KEYS]=
+{
+  KIGNORE   ,K(KCn, 0 ),K(KCn, 1 ),K(KCn, 2  ),K(KCn, 3 ),K(KCn, 4 ),K(KCn, 5  ),K(KCn, 6 ),
+  K(KCn, 7 ),K(KCn, 8 ),K(KCn, 9 ),K(KCn,10  ),K(KCn,11 ),KIGNORE   ,KIGNORE    ,KINTR     ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,K(KTf,21 ),
+  K(KTf,20 ),K(KTf,24 ),KNUMLK    ,KPAD_DV    ,KPAD_ML   ,KPAD_HS   ,KIGNORE    ,K(KMt,17 ),
+  K(KMt,23 ),K(KMt, 5 ),K(KMt,18 ),K(KMt,20  ),K(KMt,25 ),K(KMt,21 ),K(KMt, 9  ),K(KMt,15 ),
+  K(KMt,16 ),KIGNORE   ,KIGNORE   ,KIGNORE    ,KREBOOT   ,K(KTf,23 ),K(KTf,25  ),KPAD_7    ,
+  KPAD_8    ,KPAD_9    ,KPAD_MI   ,KCTRL      ,K(KMt, 1 ),K(KMt,19 ),K(KMt, 4  ),K(KMt, 6 ),
+  K(KMt, 7 ),K(KMt, 8 ),K(KMt,10 ),K(KMt,11  ),K(KMt,12 ),KIGNORE   ,KIGNORE    ,KENTER    ,
+  KPAD_4    ,KPAD_5    ,KPAD_6    ,KPAD_PL    ,KSHIFT    ,KIGNORE   ,K(KMt,26  ),K(KMt,24 ),
+  K(KMt, 3 ),K(KMt,22 ),K(KMt, 2 ),K(KMt,14  ),K(KMt,13 ),KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KSHIFT    ,K(KTc,Kcu),KPAD_1    ,KPAD_2     ,KPAD_3    ,KCAPSLK   ,KALT       ,KIGNORE   ,
+  KALTGR    ,KCTRL     ,K(KTc,Kcl),K(KTc,Kcd ),K(KTc,Kcr),KPAD_0    ,KREBOOT    ,KPAD_EN   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+  KIGNORE   ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,KIGNORE   ,KIGNORE    ,KIGNORE   ,
+};
+
+ushort *key_maps[MAX_NR_KEYMAPS] = {
+       plain_map, shift_map, altgr_map, 0,
+       ctrl_map, shift_ctrl_map, 0, 0,
+       alt_map, 0, 0, 0,
+       ctrl_alt_map,   0
+};
+
+unsigned int keymap_count = 7;
+
+/*
+ * Philosophy: most people do not define more strings, but they who do
+ * often want quite a lot of string space. So, we statically allocate
+ * the default and allocate dynamically in chunks of 512 bytes.
+ */
+
+char func_buf[] = {
+       '\033', '[', '[', 'A', 0,
+       '\033', '[', '[', 'B', 0,
+       '\033', '[', '[', 'C', 0,
+       '\033', '[', '[', 'D', 0,
+       '\033', '[', '[', 'E', 0,
+       '\033', '[', '1', '7', '~', 0,
+       '\033', '[', '1', '8', '~', 0,
+       '\033', '[', '1', '9', '~', 0,
+       '\033', '[', '2', '0', '~', 0,
+       '\033', '[', '2', '1', '~', 0,
+       '\033', '[', '2', '3', '~', 0,
+       '\033', '[', '2', '4', '~', 0,
+       '\033', '[', '2', '5', '~', 0,
+       '\033', '[', '2', '6', '~', 0,
+       '\033', '[', '2', '8', '~', 0,
+       '\033', '[', '2', '9', '~', 0,
+       '\033', '[', '3', '1', '~', 0,
+       '\033', '[', '3', '2', '~', 0,
+       '\033', '[', '3', '3', '~', 0,
+       '\033', '[', '3', '4', '~', 0,
+       '\033', '[', '1', '~', 0,
+       '\033', '[', '2', '~', 0,
+       '\033', '[', '3', '~', 0,
+       '\033', '[', '4', '~', 0,
+       '\033', '[', '5', '~', 0,
+       '\033', '[', '6', '~', 0,
+       '\033', '[', 'M', 0,
+       '\033', '[', 'P', 0,
+};
+
+char *funcbufptr = func_buf;
+int funcbufsize = sizeof(func_buf);
+int funcbufleft = 0;          /* space left */
+
+char *func_table[MAX_NR_FUNC] = {
+       func_buf + 0,
+       func_buf + 5,
+       func_buf + 10,
+       func_buf + 15,
+       func_buf + 20,
+       func_buf + 25,
+       func_buf + 31,
+       func_buf + 37,
+       func_buf + 43,
+       func_buf + 49,
+       func_buf + 55,
+       func_buf + 61,
+       func_buf + 67,
+       func_buf + 73,
+       func_buf + 79,
+       func_buf + 85,
+       func_buf + 91,
+       func_buf + 97,
+       func_buf + 103,
+       func_buf + 109,
+       func_buf + 115,
+       func_buf + 120,
+       func_buf + 125,
+       func_buf + 130,
+       func_buf + 135,
+       func_buf + 140,
+       func_buf + 145,
+       0,
+       0,
+       func_buf + 149,
+       0,
+};
+
+struct kbdiacr accent_table[MAX_DIACR] = {
+       {'`', 'A', '\300'},     {'`', 'a', '\340'},
+       {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
+       {'^', 'A', '\302'},     {'^', 'a', '\342'},
+       {'~', 'A', '\303'},     {'~', 'a', '\343'},
+       {'"', 'A', '\304'},     {'"', 'a', '\344'},
+       {'O', 'A', '\305'},     {'o', 'a', '\345'},
+       {'0', 'A', '\305'},     {'0', 'a', '\345'},
+       {'A', 'A', '\305'},     {'a', 'a', '\345'},
+       {'A', 'E', '\306'},     {'a', 'e', '\346'},
+       {',', 'C', '\307'},     {',', 'c', '\347'},
+       {'`', 'E', '\310'},     {'`', 'e', '\350'},
+       {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
+       {'^', 'E', '\312'},     {'^', 'e', '\352'},
+       {'"', 'E', '\313'},     {'"', 'e', '\353'},
+       {'`', 'I', '\314'},     {'`', 'i', '\354'},
+       {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
+       {'^', 'I', '\316'},     {'^', 'i', '\356'},
+       {'"', 'I', '\317'},     {'"', 'i', '\357'},
+       {'-', 'D', '\320'},     {'-', 'd', '\360'},
+       {'~', 'N', '\321'},     {'~', 'n', '\361'},
+       {'`', 'O', '\322'},     {'`', 'o', '\362'},
+       {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
+       {'^', 'O', '\324'},     {'^', 'o', '\364'},
+       {'~', 'O', '\325'},     {'~', 'o', '\365'},
+       {'"', 'O', '\326'},     {'"', 'o', '\366'},
+       {'/', 'O', '\330'},     {'/', 'o', '\370'},
+       {'`', 'U', '\331'},     {'`', 'u', '\371'},
+       {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
+       {'^', 'U', '\333'},     {'^', 'u', '\373'},
+       {'"', 'U', '\334'},     {'"', 'u', '\374'},
+       {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
+       {'T', 'H', '\336'},     {'t', 'h', '\376'},
+       {'s', 's', '\337'},     {'"', 'y', '\377'},
+       {'s', 'z', '\337'},     {'i', 'j', '\377'},
+};
+
+unsigned int accent_table_size = 68;
index 82b2cc51049e3fd98c41fc81f330fa796ab1290a..164ef4523a3d2151d1e6b20fd3072362892c618a 100644 (file)
@@ -56,9 +56,7 @@
 #include <asm/pgtable.h>
 #endif
 
-#ifdef MODULE
 #include <linux/module.h>
-#endif
 
 #include "fore200e.h"
 #include "suni.h"
index 2bf92251c8503fefa2690fb71203de51c7599915..1eee6d5458aac62367935213010dc8787b7aa4ac 100644 (file)
@@ -138,6 +138,8 @@ void elevator_linus(struct request *req, elevator_t *elevator,
        struct list_head *entry = real_head;
        struct request *tmp;
 
+       req->elevator_sequence = orig_latency;
+
        if (list_empty(real_head)) {
                list_add(&req->queue, real_head);
                return;
index 2ed93b30079eb43d0f20c128fc2ef8ee0ae24a48..9646adbd0235d4934771b7fd1bffb23a6ca5aea9 100644 (file)
@@ -345,8 +345,6 @@ static inline struct request *get_request(request_queue_t *q, int rw)
        register struct request *rq = NULL;
 
        if (!list_empty(&q->request_freelist)) {
-               elevator_t *e = &q->elevator;
-
                if ((q->queue_requests > QUEUE_WRITES_MAX) && (rw == WRITE))
                        return NULL;
 
@@ -355,10 +353,6 @@ static inline struct request *get_request(request_queue_t *q, int rw)
                rq->rq_status = RQ_ACTIVE;
                rq->special = NULL;
                rq->q = q;
-               if (rq->cmd == READ)
-                       rq->elevator_sequence = e->read_latency;
-               else
-                       rq->elevator_sequence = e->write_latency;
                q->queue_requests++;
        }
        return rq;
@@ -657,6 +651,13 @@ static inline void __make_request(request_queue_t * q, int rw,
                goto get_rq;
        }
 
+       /*
+        * skip first entry, for devices with active queue head
+        */
+       head = &q->queue_head;
+       if (q->head_active && !q->plugged)
+               head = head->next;
+
        el_ret = elevator->elevator_merge_fn(q, &req, bh, rw, &max_sectors, &max_segments);
        switch (el_ret) {
 
@@ -709,12 +710,12 @@ get_rq:
 
                req = __get_request_wait(q, rw);
                spin_lock_irq(&io_request_lock);
+               
+               head = &q->queue_head;
+               if (q->head_active && !q->plugged)
+                       head = head->next;
        }
 
-       head = &q->queue_head;
-       if (q->head_active && !q->plugged)
-               head = head->next;
-
 /* fill up the request-info, and add it to the queue */
        req->cmd = rw;
        req->errors = 0;
index cf145729a743f26e7e472f885ee7fb2a7dc7cde5..30e649ac06dc85d8e7f3798bcffb03648fbb5ac5 100644 (file)
@@ -318,10 +318,7 @@ obj-$(L_DECODERS) += saa7110.o saa7111.o saa7185.o
 # set when a framegrabber implements i2c support
 obj-$(L_I2C) += i2c-old.o
 
-ifeq ($(CONFIG_DZ),y)
-  L_OBJS += dz.o
-endif
-
+obj-$(CONFIG_DZ) += dz.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 
index b8165ef9893513404d4873f4f1e94fbe5724669b..d72bc629ecbdfc283cc73cf2b39f3814d13296a0 100644 (file)
@@ -1566,11 +1566,9 @@ static struct console dz_sercons = {
        NULL
 };
 
-long __init dz_serial_console_init(long kmem_start, long kmem_end)
+void __init dz_serial_console_init(l)
 {
        register_console(&dz_sercons);
-
-       return kmem_start;
 }
 
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
index 377c1b5d13618afb7c3b9ab42f403cdcef746493..b2c5493344c343534d0da896eb39bd2d93db0e4e 100644 (file)
@@ -73,7 +73,8 @@
 #define MODE_COLL      0x0010
 #define MODE_DRETRY    0x0020
 #define MODE_INTLOOP   0x0040
-#define MODE_PORT0     0x0080
+#define MODE_PORT_AUI  0x0000
+#define MODE_PORT_10BT 0x0080
 #define MODE_DRXPA     0x2000
 #define MODE_DRXBA     0x4000
 #define MODE_PROMISC   0x8000
 #define TST_LCAR       0x0800
 #define TST_LCOL       0x1000
 #define TST_UFLO       0x4000
+#define TST_BUFF       0x8000
 
 struct dev_priv {
     struct enet_statistics stats;
index f28196a2fe190bee2623c4050ddfea468ea7abe1..1b8e48e0f165caceba2941c890238c497944649c 100644 (file)
@@ -95,10 +95,8 @@ History:
 #include <asm/bitops.h>
 #include <asm/io.h>
 
-#ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
-#endif
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 2115cdac9c436d9d7d4145016f555e88c81bf7c0..4b2aacce6ea59ad6bab3746741a0d7360b75dd0b 100644 (file)
@@ -527,9 +527,11 @@ static void __init isapnp_add_irq_resource(struct pci_dev *dev,
                ptr->next = irq;
        else
                (*res)->irq = irq;
+#ifdef CONFIG_PCI
        for (i=0; i<16; i++)
                if (irq->map & i)
                        pcibios_penalize_isa_irq(i);
+#endif
 }
 
 /*
index d9f952ca6185de60174f9df122f8f4d90d7a5e97..7cbbc3f1f4e6a1ac08d2e6b7d0193341d2e34704 100644 (file)
@@ -9092,7 +9092,7 @@ aic7xxx_load_seeprom(struct aic7xxx_host *p, unsigned char *sxfrctl1)
         p->flags |= AHC_TERM_ENB_SE_LOW | AHC_TERM_ENB_SE_HIGH;
       }
     }
-    p->sc = *sc;
+    memcpy(&p->sc, sc, sizeof(struct seeprom_config));
   }
 
   p->discenable = 0;
index 2496fce816c274d6e3c801e689538555b6cd8893..698849a4d9e64abc00ecb664cc3ea663b4b19bf5 100644 (file)
@@ -668,7 +668,7 @@ static Scsi_Host_Template builtin_scsi_hosts[] =
 #endif
 /* Put I2O last so that host specific controllers always win */
 #ifdef CONFIG_I2O_SCSI
-       I2OSCSI
+       I2OSCSI,
 #endif
 /* "Removable host adapters" below this line (Parallel Port/USB/other) */
 #ifdef CONFIG_SCSI_PPA
index 825c777825ac324b8e3259b68b637846a979efed..6200afafc9afb3e2faf45bfdbe1eb40aea9cbede 100644 (file)
@@ -72,12 +72,21 @@ typedef dma_addr_t dma64_addr_t;
 #define pci64_map_sg(d,s,n,dir) pci_map_sg((d),(s),(n),(dir))
 #define pci64_unmap_single(d,a,s,dir) pci_unmap_single((d),(a),(s),(dir))
 #define pci64_unmap_sg(d,s,n,dir) pci_unmap_sg((d),(s),(n),(dir))
+#if BITS_PER_LONG > 32
+#define pci64_dma_hi32(a) ((u32) (0xffffffff & (a>>32)))
+#define pci64_dma_lo32(a) ((u32) (0xffffffff & (a)))
+#else
 #define pci64_dma_hi32(a) 0
 #define pci64_dma_lo32(a) (a)
+#endif /* BITS_PER_LONG */
 #define pci64_dma_build(hi,lo) (lo)
 #define sg_dma64_address(s) sg_dma_address(s)
 #define sg_dma64_len(s) sg_dma_len(s)
+#if BITS_PER_LONG > 32
+#define PCI64_DMA_BITS 64
+#else
 #define PCI64_DMA_BITS 32
+#endif         /* BITS_PER_LONG */
 #endif
 
 #include "qlogicfc.h"
@@ -101,15 +110,12 @@ typedef dma_addr_t dma64_addr_t;
 #define ISP2x00_FABRIC          1
 
 /*  Macros used for debugging */
-/*
-#define DEBUG_ISP2x00          1
-#define DEBUG_ISP2x00_INT      1
-#define DEBUG_ISP2x00_INTR     1
-#define DEBUG_ISP2x00_SETUP    1
-
-#define DEBUG_ISP2x00_FABRIC    1
-*/
-/* #define TRACE_ISP             1 */
+#define DEBUG_ISP2x00          0
+#define DEBUG_ISP2x00_INT      0
+#define DEBUG_ISP2x00_INTR     0
+#define DEBUG_ISP2x00_SETUP    0
+#define DEBUG_ISP2x00_FABRIC    0
+#define TRACE_ISP              0 
 
 
 #define DEFAULT_LOOP_COUNT     1000000000
@@ -1233,7 +1239,7 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
        for (i = in_ptr; i != (in_ptr - 1) && hostdata->handle_ptrs[i]; i = ((i + 1) % (QLOGICFC_REQ_QUEUE_LEN + 1)));
 
        if (!hostdata->handle_ptrs[i]) {
-               cmd->handle = i;
+               cmd->handle = cpu_to_le32(i);
                hostdata->handle_ptrs[i] = Cmnd;
                hostdata->handle_serials[i] = Cmnd->serial_number;
        } else {
@@ -1358,6 +1364,13 @@ int isp2x00_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
                                break;
                }
        }
+       /*
+        * TEST_UNIT_READY commands from scsi_scan will fail due to "overlapped
+        * commands attempted" unless we setup at least a simple queue (midlayer 
+        * will embelish this once it can do an INQUIRY command to the device)
+        */
+       else
+               cmd->control_flags |= cpu_to_le16(CFLAG_SIMPLE_TAG);
        outw(in_ptr, host->io_port + MBOX4);
        hostdata->req_in_ptr = in_ptr;
 
@@ -1541,12 +1554,14 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
                DEBUG_INTR(printk("qlogicfc%d : response queue depth %d\n", hostdata->host_id, RES_QUEUE_DEPTH(in_ptr, out_ptr)));
 
                while (out_ptr != in_ptr) {
+                       unsigned le_hand;
                        sts = (struct Status_Entry *) &hostdata->res[out_ptr*QUEUE_ENTRY_LEN];
                        out_ptr = (out_ptr + 1) & RES_QUEUE_LEN;
                  
                        TRACE("done", out_ptr, Cmnd);
                        DEBUG_INTR(isp2x00_print_status_entry(sts));
-                       if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[sts->handle])) {
+                       le_hand = le32_to_cpu(sts->handle);
+                       if (sts->hdr.entry_type == ENTRY_STATUS && (Cmnd = hostdata->handle_ptrs[le_hand])) {
                                Cmnd->result = isp2x00_return_status(Cmnd, sts);
                                hostdata->queued--;
 
@@ -1565,10 +1580,10 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
                                 * we dont have to call done because the upper
                                 * level should already know its aborted.
                                 */
-                               if (hostdata->handle_serials[sts->handle] != Cmnd->serial_number 
+                               if (hostdata->handle_serials[le_hand] != Cmnd->serial_number 
                                    || le16_to_cpu(sts->completion_status) == CS_ABORTED){
-                                       hostdata->handle_serials[sts->handle] = 0;
-                                       hostdata->handle_ptrs[sts->handle] = NULL;
+                                       hostdata->handle_serials[le_hand] = 0;
+                                       hostdata->handle_ptrs[le_hand] = NULL;
                                        outw(out_ptr, host->io_port + MBOX5);
                                        continue;
                                }
@@ -1589,7 +1604,7 @@ void isp2x00_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
                                continue;
                        }
 
-                       hostdata->handle_ptrs[sts->handle] = NULL;
+                       hostdata->handle_ptrs[le_hand] = NULL;
 
                        if (sts->completion_status == cpu_to_le16(CS_RESET_OCCURRED)
                            || (sts->status_flags & cpu_to_le16(STF_BUS_RESET)))
@@ -1912,23 +1927,14 @@ static int isp2x00_reset_hardware(struct Scsi_Host *host)
        }
 #endif
 
-#ifdef __BIG_ENDIAN
-       {
-               u64 val;
-               memcpy(&val, &hostdata->control_block.node_name, sizeof(u64));
-               hostdata->wwn = ((val & 0xff00ff00ff00ff00ULL) >> 8)
-                             | ((val & 0x00ff00ff00ff00ffULL) << 8);
-       }
-#else
-       hostdata->wwn = (u64) (hostdata->control_block.node_name[0]) << 56;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[0] & 0xff00) << 48;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0xff00) << 24;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[1] & 0x00ff) << 48;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0x00ff) << 24;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[2] & 0xff00) << 8;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0x00ff) << 8;
-       hostdata->wwn |= (u64) (hostdata->control_block.node_name[3] & 0xff00) >> 8;
-#endif
+       hostdata->wwn = (u64) (cpu_to_le16(hostdata->control_block.node_name[0])) << 56;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[0]) & 0xff00) << 48;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0xff00) << 24;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[1]) & 0x00ff) << 48;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0x00ff) << 24;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[2]) & 0xff00) << 8;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0x00ff) << 8;
+       hostdata->wwn |= (u64) (cpu_to_le16(hostdata->control_block.node_name[3]) & 0xff00) >> 8;
 
        /* FIXME: If the DMA transfer goes one way only, this should use PCI_DMA_TODEVICE and below as well. */
        busaddr = pci64_map_single(hostdata->pci_dev, &hostdata->control_block, sizeof(hostdata->control_block),
index e00e8c64510a954c9f863c2032dc9605534b263f..10539d3db8fce274de989e8c3ecebaa27e26fc56 100644 (file)
@@ -62,7 +62,7 @@
  * determined for each queue request anew.
  */
 
-#if PCI64_DMA_BITS > 32
+#if BITS_PER_LONG > 32
 #define DATASEGS_PER_COMMAND 2
 #define DATASEGS_PER_CONT 5
 #else
index bdc3e8002f478287635a6013493a291d6cd46daf..a605233c0ccad0e2c059aa406f74ce8fe181822b 100644 (file)
@@ -12,7 +12,7 @@
    Copyright 1992 - 2000 Kai Makisara
    email Kai.Makisara@metla.fi
 
-   Last modified: Sun Apr 23 23:41:32 2000 by makisara@kai.makisara.local
+   Last modified: Sat Jun 17 15:21:49 2000 by makisara@kai.makisara.local
    Some small formal changes - aeb, 950809
 
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
 
 #include "constants.h"
 
-static int buffer_kbs = 0;
-static int write_threshold_kbs = 0;
+static int buffer_kbs;
+static int write_threshold_kbs;
 static int max_buffers = (-1);
-static int max_sg_segs = 0;
+static int max_sg_segs;
 
 MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI Tape Driver");
@@ -138,7 +138,7 @@ static int st_max_sg_segs = ST_MAX_SG;
 
 static Scsi_Tape **scsi_tapes = NULL;
 
-static int modes_defined = FALSE;
+static int modes_defined;
 
 static ST_buffer *new_tape_buffer(int, int);
 static int enlarge_buffer(ST_buffer *, int, int);
@@ -870,7 +870,7 @@ static int scsi_tape_open(struct inode *inode, struct file *filp)
 static int scsi_tape_flush(struct file *filp)
 {
        int result = 0, result2;
-       static unsigned char cmd[MAX_COMMAND_SIZE];
+       unsigned char cmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
        Scsi_Tape *STp;
        ST_mode *STm;
@@ -1027,7 +1027,7 @@ static ssize_t
        ssize_t retval = 0;
        int write_threshold;
        int doing_write = 0;
-       static unsigned char cmd[MAX_COMMAND_SIZE];
+       unsigned char cmd[MAX_COMMAND_SIZE];
        const char *b_point;
        Scsi_Request *SRpnt = NULL;
        Scsi_Tape *STp;
@@ -1380,7 +1380,7 @@ static ssize_t
 static long read_tape(Scsi_Tape *STp, long count, Scsi_Request ** aSRpnt)
 {
        int transfer, blks, bytes;
-       static unsigned char cmd[MAX_COMMAND_SIZE];
+       unsigned char cmd[MAX_COMMAND_SIZE];
        Scsi_Request *SRpnt;
        ST_mode *STm;
        ST_partstat *STps;
@@ -2945,24 +2945,34 @@ static int st_ioctl(struct inode *inode, struct file *file,
 
                if (mtc.mt_op == MTSETPART) {
                        if (!STp->can_partitions ||
-                           mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS)
-                               return (-EINVAL);
+                           mtc.mt_count < 0 || mtc.mt_count >= ST_NBR_PARTITIONS) {
+                               retval = (-EINVAL);
+                               goto out;
+                       }
                        if (mtc.mt_count >= STp->nbr_partitions &&
-                       (STp->nbr_partitions = nbr_partitions(STp)) < 0)
-                               return (-EIO);
-                       if (mtc.mt_count >= STp->nbr_partitions)
-                               return (-EINVAL);
+                           (STp->nbr_partitions = nbr_partitions(STp)) < 0) {
+                               retval = (-EIO);
+                               goto out;
+                       }
+                       if (mtc.mt_count >= STp->nbr_partitions) {
+                               retval = (-EINVAL);
+                               goto out;
+                       }
                        STp->new_partition = mtc.mt_count;
                        retval = 0;
                        goto out;
                }
 
                if (mtc.mt_op == MTMKPART) {
-                       if (!STp->can_partitions)
-                               return (-EINVAL);
+                       if (!STp->can_partitions) {
+                               retval = (-EINVAL);
+                               goto out;
+                       }
                        if ((i = st_int_ioctl(STp, MTREW, 0)) < 0 ||
-                           (i = partition_tape(STp, mtc.mt_count)) < 0)
-                               return i;
+                           (i = partition_tape(STp, mtc.mt_count)) < 0) {
+                               retval = i;
+                               goto out;
+                       }
                        for (i = 0; i < ST_NBR_PARTITIONS; i++) {
                                STp->ps[i].rw = ST_IDLE;
                                STp->ps[i].at_sm = 0;
index 6342e511a50bf8f3725b9e3f83ef48f93556eb12..01fb315ab37fcd36e0a6454c412e4f475b014edd 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/iomd.h>
+#include <asm/irq.h>
 #include <asm/system.h>
 
 #include "sound_config.h"
index c3cce34c36683f852527250b7d03f2c51e89ad19..dddf52c608e80f561f94aa1958244c1d1cc69165 100644 (file)
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
 *
+*  (6/22/2000) pberger and borchers
+*    -- Made cond_wait_... inline--apparently on SPARC the flags arg
+*       to spin_lock_irqsave cannot be passed to another function
+*       to call spin_unlock_irqrestore.  Thanks to Pauline Middelink.
+*    -- In digi_set_modem_signals the inner nested spin locks use just
+*       spin_lock() rather than spin_lock_irqsave().  The old code
+*       mistakenly left interrupts off.  Thanks to Pauline Middelink.
+*    -- copy_from_user (which can sleep) is no longer called while a
+*       spinlock is held.  We copy to a local buffer before getting
+*       the spinlock--don't like the extra copy but the code is simpler.
+*    -- Printk and dbg are no longer called while a spin lock is held.
+*
 *  (6/4/2000) pberger and borchers
 *    -- Replaced separate calls to spin_unlock_irqrestore and
 *       interruptible_sleep_on_interruptible with a new function
 *  - All sleeps use a timeout of DIGI_RETRY_TIMEOUT before looping to
 *    recheck the condition they are sleeping on.  This is defensive,
 *    in case a wake up is lost.
+*  - Following Documentation/DocBook/kernel-locking.pdf no spin locks
+*    are held when calling copy_to/from_user or printk.
 *    
-*  $Id: digi_acceleport.c,v 1.56 2000/06/07 22:47:30 root Exp root $
+*  $Id: digi_acceleport.c,v 1.60 2000/06/23 17:43:17 root Exp root $
 */
 
 #include <linux/config.h>
@@ -402,7 +416,7 @@ struct usb_serial_device_type digi_acceleport_device = {
 *  wake ups.  This is used to implement condition variables.
 */
 
-static long cond_wait_interruptible_timeout_irqrestore(
+static inline long cond_wait_interruptible_timeout_irqrestore(
        wait_queue_head_t *q, long timeout,
        spinlock_t *lock, unsigned long flags )
 {
@@ -515,17 +529,17 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_port_num, count );
                if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
                        count -= len;
                        buf += len;
-               } else {
-                       dbg(
-                       "digi_write_oob_command: usb_submit_urb failed, ret=%d",
-                       ret );
-                       break;
                }
 
        }
 
        spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
 
+       if( ret ) {
+               dbg( "digi_write_oob_command: usb_submit_urb failed, ret=%d",
+               ret );
+       }
+
        return( ret );
 
 }
@@ -569,8 +583,8 @@ count );
                }
 
                /* len must be a multiple of 4 and small enough to */
-               /* guarantee the write will send all data (or none), */
-               /* so commands are not split */
+               /* guarantee the write will send buffered data first, */
+               /* so commands are in order with data and not split */
                len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len );
                if( len > 4 )
                        len &= ~3;
@@ -588,35 +602,21 @@ count );
                        port->write_urb->transfer_buffer_length = len;
                }
 
-#ifdef DEBUG_DATA
- {
-       int i;
-
-       printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=",
-               priv->dp_port_num, port->write_urb->transfer_buffer_length );
-       for( i=0; i<port->write_urb->transfer_buffer_length; ++i ) {
-               printk( "%.2x ",
-               ((unsigned char *)port->write_urb->transfer_buffer)[i] );
-       }
-       printk( "\n" );
- }
-#endif
-
                if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
                        priv->dp_buf_len = 0;
                        count -= len;
                        buf += len;
-               } else {
-                       dbg(
-                       "digi_write_inb_command: usb_submit_urb failed, ret=%d",
-                       ret );
-                       break;
                }
 
        }
 
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
 
+       if( ret ) {
+               dbg( "digi_write_inb_command: usb_submit_urb failed, ret=%d",
+               ret );
+       }
+
        return( ret );
 
 }
@@ -647,10 +647,10 @@ dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
 port_priv->dp_port_num, modem_signals );
 
        spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
-       spin_lock_irqsave( &port_priv->dp_port_lock, flags );
+       spin_lock( &port_priv->dp_port_lock );
 
        while( oob_port->write_urb->status == -EINPROGRESS ) {
-               spin_unlock_irqrestore( &port_priv->dp_port_lock, flags );
+               spin_unlock( &port_priv->dp_port_lock );
                cond_wait_interruptible_timeout_irqrestore(
                        &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
                        &oob_priv->dp_port_lock, flags );
@@ -658,7 +658,7 @@ port_priv->dp_port_num, modem_signals );
                        return( -EINTR );
                }
                spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
-               spin_lock_irqsave( &port_priv->dp_port_lock, flags );
+               spin_lock( &port_priv->dp_port_lock );
        }
 
        data[0] = DIGI_CMD_SET_DTR_SIGNAL;
@@ -679,14 +679,16 @@ port_priv->dp_port_num, modem_signals );
                port_priv->dp_modem_signals =
                        (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
                        | (modem_signals&(TIOCM_DTR|TIOCM_RTS));
-       } else {
-               dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d",
-                       ret );
        }
 
-       spin_unlock_irqrestore( &port_priv->dp_port_lock, flags );
+       spin_unlock( &port_priv->dp_port_lock );
        spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
 
+       if( ret ) {
+               dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d",
+               ret );
+       }
+
        return( ret );
 
 }
@@ -1046,12 +1048,19 @@ static int digi_write( struct usb_serial_port *port, int from_user,
        int ret,data_len,new_len;
        digi_private_t *priv = (digi_private_t *)(port->private);
        unsigned char *data = port->write_urb->transfer_buffer;
+       unsigned char user_buf[64];     /* 64 bytes is max USB bulk packet */
        unsigned long flags = 0;
 
 
 dbg( "digi_write: TOP: port=%d, count=%d, from_user=%d, in_interrupt=%d",
 priv->dp_port_num, count, from_user, in_interrupt() );
 
+       /* copy user data (which can sleep) before getting spin lock */
+       count = MIN( 64, MIN( count, port->bulk_out_size-2 ) );
+       if( from_user && copy_from_user( user_buf, buf, count ) ) {
+               return( -EFAULT );
+       }
+
        /* be sure only one write proceeds at a time */
        /* there are races on the port private buffer */
        /* and races to check write_urb->status */
@@ -1096,40 +1105,19 @@ priv->dp_port_num, count, from_user, in_interrupt() );
        data += priv->dp_buf_len;
 
        /* copy in new data */
-       if( from_user ) {
-               if( copy_from_user( data, buf, new_len ) ) {
-                       spin_unlock_irqrestore( &priv->dp_port_lock, flags );
-                       return( -EFAULT );
-               }
-       } else {
-               memcpy( data, buf, new_len );
-       }  
-
-#ifdef DEBUG_DATA
- {
-       int i;
-
-       printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=",
-               priv->dp_port_num, port->write_urb->transfer_buffer_length );
-       for( i=0; i<port->write_urb->transfer_buffer_length; ++i ) {
-               printk( "%.2x ",
-               ((unsigned char *)port->write_urb->transfer_buffer)[i] );
-       }
-       printk( "\n" );
- }
-#endif
+       memcpy( data, from_user ? user_buf : buf, new_len );
 
        if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
                ret = new_len;
                priv->dp_buf_len = 0;
-       } else {
-               dbg( "digi_write: usb_submit_urb failed, ret=%d",
-                       ret );
        }
 
        /* return length of new data written, or error */
-dbg( "digi_write: returning %d", ret );
        spin_unlock_irqrestore( &priv->dp_port_lock, flags );
+       if( ret < 0 ) {
+               dbg( "digi_write: usb_submit_urb failed, ret=%d", ret );
+       }
+dbg( "digi_write: returning %d", ret );
        return( ret );
 
 } 
@@ -1175,24 +1163,8 @@ dbg( "digi_write_bulk_callback: TOP: port=%d", priv->dp_port_num );
                memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf,
                        priv->dp_buf_len );
 
-#ifdef DEBUG_DATA
- {
-       int i;
-
-       printk( KERN_DEBUG __FILE__ ": digi_write_bulk_callback: port=%d, length=%d, data=",
-               priv->dp_port_num, port->write_urb->transfer_buffer_length );
-       for( i=0; i<port->write_urb->transfer_buffer_length; ++i ) {
-               printk( "%.2x ",
-               ((unsigned char *)port->write_urb->transfer_buffer)[i] );
-       }
-       printk( "\n" );
- }
-#endif
-
                if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
                        priv->dp_buf_len = 0;
-               } else {
-                       dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d", ret );
                }
 
        }
@@ -1202,6 +1174,11 @@ dbg( "digi_write_bulk_callback: TOP: port=%d", priv->dp_port_num );
 
        spin_unlock( &priv->dp_port_lock );
 
+       if( ret ) {
+               dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d",
+               ret );
+       }
+
        /* also queue up a wakeup at scheduler time, in case we */
        /* lost the race in write_chan(). */
        priv->dp_tasks.routine = (void *)digi_wakeup_write_lock;
@@ -1219,8 +1196,6 @@ static int digi_write_room( struct usb_serial_port *port )
        unsigned long flags = 0;
 
 
-dbg( "digi_write_room: TOP: port=%d", priv->dp_port_num );
-
        spin_lock_irqsave( &priv->dp_port_lock, flags );
 
        if( port->write_urb->status == -EINPROGRESS )
@@ -1242,8 +1217,6 @@ static int digi_chars_in_buffer( struct usb_serial_port *port )
        digi_private_t *priv = (digi_private_t *)(port->private);
 
 
-dbg( "digi_chars_in_buffer: TOP: port=%d", priv->dp_port_num );
-
        if( port->write_urb->status == -EINPROGRESS ) {
 dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 );
                /* return( port->bulk_out_size - 2 ); */
@@ -1455,13 +1428,14 @@ static int digi_startup_device( struct usb_serial *serial )
        int i,ret = 0;
 
 
-       spin_lock( &startup_lock );
-
        /* be sure this happens exactly once */
+       spin_lock( &startup_lock );
        if( device_startup ) {
                spin_unlock( &startup_lock );
                return( 0 );
        }
+       device_startup = 1;
+       spin_unlock( &startup_lock );
 
        /* start reading from each bulk in endpoint for the device */
        for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
@@ -1474,10 +1448,6 @@ static int digi_startup_device( struct usb_serial *serial )
 
        }
 
-       device_startup = 1;
-
-       spin_unlock( &startup_lock );
-
        return( ret );
 
 }
@@ -1595,17 +1565,6 @@ dbg( "digi_read_bulk_callback: TOP: port=%d", priv->dp_port_num );
                goto resubmit;
        }
 
-#ifdef DEBUG_DATA
-if( urb->actual_length ) {
-       printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: port=%d, length=%d, data=",
-               priv->dp_port_num, urb->actual_length );
-       for( i=0; i<urb->actual_length; ++i ) {
-               printk( "%.2x ", ((unsigned char *)urb->transfer_buffer)[i] );
-       }
-       printk( "\n" );
-}
-#endif
-
        if( urb->actual_length != len + 2 )
                err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", priv->dp_port_num, opcode, len, urb->actual_length, status );
 
index b8e2e1d7445f5e0a5d5b041521a9991b9d157ee2..430a8fa64781bfea651524cf80fc850b140e3a4d 100644 (file)
@@ -51,6 +51,8 @@ struct usb_serial_port {
 
        wait_queue_head_t       write_wait;
 
+       struct tq_struct        tqueue;         /* task queue for line discipline waking up */
+       
        void *                  private;        /* data private to the specific port */
 };
 
@@ -178,6 +180,5 @@ static inline int port_paranoia_check (struct usb_serial_port *port, const char
        return 0;
 }
 
-
 #endif /* ifdef __LINUX_USB_SERIAL_H */
 
index d60fd8e333fb7e7182deb258494ec87179dbab9d..261d5ac006ad406cfa4d3a0572f3625a1d745e2e 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (06/25/2000) gkh
+ *     Changed generic_write_bulk_callback to not call wake_up_interruptible
+ *     directly, but to have port_softint do it at a safer time.
+ *
  * (06/23/2000) gkh
  *     Cleaned up debugging statements in a quest to find UHCI timeout bug.
  *
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
        #define DEBUG
@@ -803,36 +809,32 @@ static int generic_write (struct usb_serial_port *port, int from_user, const uns
 static int generic_write_room (struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       int room;
+       int room = 0;
 
        dbg(__FUNCTION__ " - port %d", port->number);
        
-       if (serial->num_bulk_out) {
-               if (port->write_urb->status == -EINPROGRESS)
-                       room = 0;
-               else
+       if (serial->num_bulk_out)
+               if (port->write_urb->status != -EINPROGRESS)
                        room = port->bulk_out_size;
-               dbg(__FUNCTION__ " returns %d", room);
-               return (room);
-       }
        
-       return (0);
+       dbg(__FUNCTION__ " - returns %d", room);
+       return (room);
 }
 
 
 static int generic_chars_in_buffer (struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
+       int chars = 0;
 
        dbg(__FUNCTION__ " - port %d", port->number);
        
-       if (serial->num_bulk_out) {
-               if (port->write_urb->status == -EINPROGRESS) {
-                       return (port->bulk_out_size);
-               }
-       }
+       if (serial->num_bulk_out)
+               if (port->write_urb->status == -EINPROGRESS)
+                       chars = port->write_urb->transfer_buffer_length;
 
-       return (0);
+       dbg (__FUNCTION__ " - returns %d", chars);
+       return (chars);
 }
 
 
@@ -844,9 +846,10 @@ static void generic_read_bulk_callback (struct urb *urb)
        unsigned char *data = urb->transfer_buffer;
        int i;
 
-       dbg (__FUNCTION__ " - enter");
+       dbg(__FUNCTION__ " - port %d", port->number);
        
        if (!serial) {
+               dbg(__FUNCTION__ " - bad serial pointer, exiting");
                return;
        }
 
@@ -877,8 +880,6 @@ static void generic_read_bulk_callback (struct urb *urb)
        if (usb_submit_urb(urb))
                dbg(__FUNCTION__ " - failed resubmitting read urb");
 
-       dbg (__FUNCTION__ " - exit");
-       
        return;
 }
 
@@ -887,11 +888,11 @@ static void generic_write_bulk_callback (struct urb *urb)
 {
        struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
        struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
-       struct tty_struct *tty;
 
-       dbg (__FUNCTION__ " - enter");
+       dbg(__FUNCTION__ " - port %d", port->number);
        
        if (!serial) {
+               dbg(__FUNCTION__ " - bad serial pointer, exiting");
                return;
        }
 
@@ -900,18 +901,36 @@ static void generic_write_bulk_callback (struct urb *urb)
                return;
        }
 
+       queue_task(&port->tqueue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+       
+       return;
+}
+
+
+static void port_softint(void *private)
+{
+       struct usb_serial_port *port = (struct usb_serial_port *)private;
+       struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+       struct tty_struct *tty;
+
+       dbg(__FUNCTION__ " - port %d", port->number);
+       
+       if (!serial) {
+               return;
+       }
+       
        tty = port->tty;
-       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
+               dbg(__FUNCTION__ " - write wakeup call.");
                (tty->ldisc.write_wakeup)(tty);
+       }
 
        wake_up_interruptible(&tty->write_wait);
-       
-       dbg (__FUNCTION__ " - exit");
-       
-       return;
 }
 
 
+
 static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
 {
        struct usb_serial *serial = NULL;
@@ -1117,6 +1136,8 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum)
                port->number = i + serial->minor;
                port->serial = serial;
                port->magic = USB_SERIAL_PORT_MAGIC;
+               port->tqueue.routine = port_softint;
+               port->tqueue.data = port;
        }
        
        /* initialize the devfs nodes for this device and let the user know what ports we are bound to */
index 8be2dd35181fa4d29539586185332277549b6502..fa7f475c64ea6789f90a2da03285cbdf4284387f 100644 (file)
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (06/25/2000) gkh
+ *     Fixed bug in visor_unthrottle that should help with the disconnect in PPP
+ *     bug that people have been reporting.
+ *
  * (06/23/2000) gkh
  *     Cleaned up debugging statements in a quest to find UHCI timeout bug.
  *
@@ -137,7 +141,7 @@ static void visor_unthrottle (struct usb_serial_port *port)
 {
        dbg(__FUNCTION__ " - port %d", port->number);
 
-       if (usb_unlink_urb (port->read_urb))
+       if (usb_submit_urb (port->read_urb))
                dbg(__FUNCTION__ " - usb_submit_urb(read bulk) failed");
 
        return;
index d42448fbf8b08648ea2dbaabf89ec4826ae81c3b..019a86a8e2ef669e42ade2797cf39ea192e2cd5c 100644 (file)
@@ -175,9 +175,9 @@ static struct board {
        const char *name;
 } dev_list[] = {
        {
-       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300, "SIS 300"}, {
-       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540, "SIS 540"}, {
-       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, "SIS 630"}, {
+       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_300,  "SIS 300"}, {
+       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5300, "SIS 540"}, {
+       PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_6300, "SIS 630"}, {
        0, 0, NULL}
 };
 
index 5e49df10bde686f3fc3c80721fa3149d7e17769e..38f16f061b843c87cca96cdd10eb7aef42da1b90 100644 (file)
@@ -666,9 +666,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                                    interpreter,
                                                    &interp_load_addr);
 
-               lock_kernel();
+               allow_write_access(interpreter);
                fput(interpreter);
-               unlock_kernel();
                kfree(elf_interpreter);
 
                if (elf_entry == ~0UL) {
@@ -755,9 +754,8 @@ out:
 
        /* error cleanup */
 out_free_dentry:
-       lock_kernel();
+       allow_write_access(interpreter);
        fput(interpreter);
-       unlock_kernel();
 out_free_interp:
        if (elf_interpreter)
                kfree(elf_interpreter);
index 1b18094eb68e08eb3f9f3e8f9e7af091811de2c3..95c24a70a3d96cc836c4110c29b097484eb61578 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/binfmts.h>
 #include <linux/elf.h>
 #include <linux/init.h>
+#include <linux/file.h>
 
 
 #define EM86_INTERP    "/usr/bin/em86"
@@ -43,6 +44,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
        }
 
        bprm->sh_bang++;        /* Well, the bang-shell is implicit... */
+       allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
 
index 0d44c3d4ed2a384a0056f28aeeb7fe312841b6ad..f9c30df1bc156223e9f03bd4063cb8358996ab94 100644 (file)
@@ -201,6 +201,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        if (!fmt)
                goto _ret;
 
+       allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
 
index dc78f8389c26106bbbec090ef6dc3f326b72f0b0..3d5023e2d6347784816ca75c223a48ffee6cc9b0 100644 (file)
@@ -29,6 +29,7 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
         */
 
        bprm->sh_bang++;
+       allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
 
index c455a735d7699c73a24da17f7f00f5cd959b03f6..3938e851f95eef45a7b76a8ef737e9a30648c0d8 100644 (file)
@@ -597,6 +597,8 @@ int blkdev_get(struct block_device *bdev, mode_t mode, unsigned flags, int kind)
                                ret = bdev->bd_op->open(fake_inode, &fake_file);
                        if (!ret)
                                atomic_inc(&bdev->bd_openers);
+                       else if (!atomic_read(&bdev->bd_openers))
+                               bdev->bd_op = NULL;
                        iput(fake_inode);
                }
        }
@@ -617,6 +619,8 @@ int blkdev_open(struct inode * inode, struct file * filp)
                        ret = bdev->bd_op->open(inode,filp);
                if (!ret)
                        atomic_inc(&bdev->bd_openers);
+               else if (!atomic_read(&bdev->bd_openers))
+                       bdev->bd_op = NULL;
        }       
        up(&bdev->bd_sem);
        return ret;
index 47d690fa4463ea9eb6b542c3554ea7b2053fa19d..fe7a36d2e6aa12f2cb4388f77f518c8aa5c1105b 100644 (file)
@@ -360,12 +360,7 @@ asmlinkage long sys_fsync(unsigned int fd)
                goto out;
 
        dentry = file->f_dentry;
-       if (!dentry)
-               goto out_putf;
-
        inode = dentry->d_inode;
-       if (!inode)
-               goto out_putf;
 
        err = -EINVAL;
        if (!file->f_op || !file->f_op->fsync)
@@ -395,12 +390,7 @@ asmlinkage long sys_fdatasync(unsigned int fd)
                goto out;
 
        dentry = file->f_dentry;
-       if (!dentry)
-               goto out_putf;
-
        inode = dentry->d_inode;
-       if (!inode)
-               goto out_putf;
 
        err = -EINVAL;
        if (!file->f_op || !file->f_op->fsync)
@@ -2101,6 +2091,7 @@ static int grow_buffers(int size)
        spin_unlock(&free_list[isize].lock);
 
        page->buffers = bh;
+       page->flags &= ~(1 << PG_referenced);
        lru_cache_add(page);
        atomic_inc(&buffermem_pages);
        return 1;
index 2ab337341ce674fb87315c596c3a4f9f882b19be..ce1031e3b0ddc908b0a26f107ad6fbaf908c083e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -101,37 +101,54 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
  */
 asmlinkage long sys_uselib(const char * library)
 {
-       int fd, retval;
        struct file * file;
+       struct nameidata nd;
+       int error;
 
-       fd = sys_open(library, 0, 0);
-       if (fd < 0)
-               return fd;
-       file = fget(fd);
-       retval = -ENOEXEC;
-       if (file) {
-               if(file->f_op && file->f_op->read) {
-                       struct linux_binfmt * fmt;
+       error = user_path_walk(library, &nd);
+       if (error)
+               goto out;
 
-                       read_lock(&binfmt_lock);
-                       for (fmt = formats ; fmt ; fmt = fmt->next) {
-                               if (!fmt->load_shlib)
-                                       continue;
-                               if (!try_inc_mod_count(fmt->module))
-                                       continue;
-                               read_unlock(&binfmt_lock);
-                               retval = fmt->load_shlib(file);
-                               read_lock(&binfmt_lock);
-                               put_binfmt(fmt);
-                               if (retval != -ENOEXEC)
-                                       break;
-                       }
+       error = -EINVAL;
+       if (!S_ISREG(nd.dentry->d_inode->i_mode))
+               goto exit;
+
+       error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC);
+       if (error)
+               goto exit;
+
+       lock_kernel();
+       file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
+       unlock_kernel();
+       error = PTR_ERR(file);
+       if (IS_ERR(file))
+               goto out;
+
+       error = -ENOEXEC;
+       if(file->f_op && file->f_op->read) {
+               struct linux_binfmt * fmt;
+
+               read_lock(&binfmt_lock);
+               for (fmt = formats ; fmt ; fmt = fmt->next) {
+                       if (!fmt->load_shlib)
+                               continue;
+                       if (!try_inc_mod_count(fmt->module))
+                               continue;
                        read_unlock(&binfmt_lock);
+                       error = fmt->load_shlib(file);
+                       read_lock(&binfmt_lock);
+                       put_binfmt(fmt);
+                       if (error != -ENOEXEC)
+                               break;
                }
-               fput(file);
+               read_unlock(&binfmt_lock);
        }
-       sys_close(fd);
-       return retval;
+       fput(file);
+out:
+       return error;
+exit:
+       path_release(&nd);
+       goto out;
 }
 
 /*
@@ -319,6 +336,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
 struct file *open_exec(const char *name)
 {
        struct nameidata nd;
+       struct inode *inode;
        struct file *file;
        int err = 0;
 
@@ -328,14 +346,22 @@ struct file *open_exec(const char *name)
        unlock_kernel();
        file = ERR_PTR(err);
        if (!err) {
+               inode = nd.dentry->d_inode;
                file = ERR_PTR(-EACCES);
-               if (S_ISREG(nd.dentry->d_inode->i_mode)) {
-                       int err = permission(nd.dentry->d_inode, MAY_EXEC);
+               if (!IS_NOEXEC(inode) && S_ISREG(inode->i_mode)) {
+                       int err = permission(inode, MAY_EXEC);
                        file = ERR_PTR(err);
                        if (!err) {
                                lock_kernel();
                                file = dentry_open(nd.dentry, nd.mnt, O_RDONLY);
                                unlock_kernel();
+                               if (!IS_ERR(file)) {
+                                       err = deny_write_access(file);
+                                       if (err) {
+                                               fput(file);
+                                               file = ERR_PTR(err);
+                                       }
+                               }
 out:
                                return file;
                        }
@@ -540,23 +566,13 @@ static inline int must_not_trace_exec(struct task_struct * p)
 int prepare_binprm(struct linux_binprm *bprm)
 {
        int mode;
-       int retval,id_change,cap_raised;
+       int id_change,cap_raised;
        struct inode * inode = bprm->file->f_dentry->d_inode;
 
        mode = inode->i_mode;
-       if (!S_ISREG(mode))                     /* must be regular file */
-               return -EACCES;
-       if (!(mode & 0111))                     /* with at least _one_ execute bit set */
+       /* Huh? We had already checked for MAY_EXEC, WTF do we check this? */
+       if (!(mode & 0111))     /* with at least _one_ execute bit set */
                return -EACCES;
-       if (IS_NOEXEC(inode))                   /* FS mustn't be mounted noexec */
-               return -EACCES;
-       if (!inode->i_sb)
-               return -EACCES;
-       if ((retval = permission(inode, MAY_EXEC)) != 0)
-               return retval;
-       /* better not execute files which are being written to */
-       if (atomic_read(&inode->i_writecount) > 0)
-               return -ETXTBSY;
 
        bprm->e_uid = current->euid;
        bprm->e_gid = current->egid;
@@ -728,6 +744,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                char * dynloader[] = { "/sbin/loader" };
                struct file * file;
 
+               allow_write_access(bprm->file);
                fput(bprm->file);
                bprm->file = NULL;
 
@@ -761,6 +778,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
                        retval = fn(bprm, regs);
                        if (retval >= 0) {
                                put_binfmt(fmt);
+                               allow_write_access(bprm->file);
                                if (bprm->file)
                                        fput(bprm->file);
                                bprm->file = NULL;
@@ -822,11 +840,13 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
        bprm.loader = 0;
        bprm.exec = 0;
        if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
+               allow_write_access(file);
                fput(file);
                return bprm.argc;
        }
 
        if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {
+               allow_write_access(file);
                fput(file);
                return bprm.envc;
        }
@@ -855,6 +875,7 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
 
 out:
        /* Something went wrong, return the inode and free the argument pages*/
+       allow_write_access(bprm.file);
        if (bprm.file)
                fput(bprm.file);
 
index aa6a599fc0a5258004a174a568f3ed4418699735..d3af3b99239bc7d0a230b417d081979cf97427d0 100644 (file)
@@ -593,7 +593,6 @@ struct super_block * ext2_read_super (struct super_block * sb, void * data,
        /*
         * set up enough so that it can read an inode
         */
-       sb->s_dev = dev;
        sb->s_op = &ext2_sops;
        sb->s_root = d_alloc_root(iget(sb, EXT2_ROOT_INO));
        if (!sb->s_root) {
index f6e4e1651a278bba43e6b91b9130fb151186a963..37e32a0126b95718965c6aa7f86bbc5668fea888 100644 (file)
@@ -252,8 +252,8 @@ asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
                                err = sock_fcntl (filp, cmd, arg);
                        break;
        }
-       fput(filp);
        unlock_kernel();
+       fput(filp);
 out:
        return err;
 }
index ecaa4689677f233efea5f039c53dc1550e330fdd..5c722143dffc29b73fee1b25e139b0ec7a765bd1 100644 (file)
@@ -16,9 +16,7 @@
 static kmem_cache_t *filp_cache;
 
 /* sysctl tunables... */
-int nr_files;          /* read only */
-int nr_free_files;     /* read only */
-int max_files = NR_FILE;/* tunable */
+struct files_stat_struct files_stat = {0, 0, NR_FILE};
 
 /* Here the new files go */
 static LIST_HEAD(anon_list);
@@ -53,11 +51,11 @@ struct file * get_empty_filp(void)
        struct file * f;
 
        file_list_lock();
-       if (nr_free_files > NR_RESERVED_FILES) {
+       if (files_stat.nr_free_files > NR_RESERVED_FILES) {
        used_one:
                f = list_entry(free_list.next, struct file, f_list);
                list_del(&f->f_list);
-               nr_free_files--;
+               files_stat.nr_free_files--;
        new_one:
                file_list_unlock();
                memset(f, 0, sizeof(*f));
@@ -73,25 +71,25 @@ struct file * get_empty_filp(void)
        /*
         * Use a reserved one if we're the superuser
         */
-       if (nr_free_files && !current->euid)
+       if (files_stat.nr_free_files && !current->euid)
                goto used_one;
        /*
         * Allocate a new one if we're below the limit.
         */
-       if (nr_files < max_files) {
+       if (files_stat.nr_files < files_stat.max_files) {
                file_list_unlock();
                f = kmem_cache_alloc(filp_cache, SLAB_KERNEL);
                file_list_lock();
                if (f) {
-                       nr_files++;
+                       files_stat.nr_files++;
                        goto new_one;
                }
                /* Big problems... */
                printk("VFS: filp allocation failed\n");
 
-       } else if (max_files > old_max) {
-               printk("VFS: file-max limit %d reached\n", max_files);
-               old_max = max_files;
+       } else if (files_stat.max_files > old_max) {
+               printk("VFS: file-max limit %d reached\n", files_stat.max_files);
+               old_max = files_stat.max_files;
        }
        file_list_unlock();
        return NULL;
@@ -148,7 +146,7 @@ void _fput(struct file *file)
        file_list_lock();
        list_del(&file->f_list);
        list_add(&file->f_list, &free_list);
-       nr_free_files++;
+       files_stat.nr_free_files++;
        file_list_unlock();
 }
 
@@ -160,7 +158,7 @@ void put_filp(struct file *file)
                file_list_lock();
                list_del(&file->f_list);
                list_add(&file->f_list, &free_list);
-               nr_free_files++;
+               files_stat.nr_free_files++;
                file_list_unlock();
        }
 }
index b09ad98eacc670b792794c9a171d1fcee00611c4..5684801df2a10af9603093b2243d381998f83289 100644 (file)
@@ -330,7 +330,15 @@ int hpfs_unlink(struct inode *dir, struct dentry *dentry)
                struct iattr newattrs;
                int err;
                hpfs_unlock_2inodes(dir, inode);
-               if (rep || dentry->d_count > 1 || permission(inode, MAY_WRITE) || get_write_access(inode)) goto ret;
+               if (rep)
+                       goto ret;
+               d_drop(dentry);
+               if (dentry->d_count > 1 ||
+                   permission(inode, MAY_WRITE) ||
+                   get_write_access(inode)) {
+                       d_rehash(dentry);
+                       goto ret;
+               }
                /*printk("HPFS: truncating file before delete.\n");*/
                down(&inode->i_sem);
                newattrs.ia_size = 0;
index 16ad5ec267c379309c61c887c8db2fd903061767..f02d766bd37882ee5bfb17895d8bf0d70475b97d 100644 (file)
@@ -107,8 +107,8 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                        else if (filp->f_op && filp->f_op->ioctl)
                                error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
        }
-       fput(filp);
        unlock_kernel();
+       fput(filp);
 
 out:
        return error;
index 50100038102452ff26329e49fa72b7f0abbd080f..fcda2fd6162a19da009db9bbab42adcc85df8cc1 100644 (file)
  *     if the pathname has trailing slashes - follow.
  *     otherwise - don't follow.
  * (applied in that order).
+ *
+ * [Jun 2000 AV] Inconsistent behaviour of open() in case if flags==O_CREAT
+ * restored for 2.4. This is the last surviving part of old 4.2BSD bug.
+ * During the 2.4 we need to fix the userland stuff depending on it -
+ * hopefully we will be able to get rid of that wart in 2.5. So far only
+ * XEmacs seems to be relying on it...
  */
 
 /* In order to reduce some races, while at the same time doing additional
@@ -191,21 +197,35 @@ int permission(struct inode * inode,int mask)
  * < 0: (-i_writecount) vm_area_structs with VM_DENYWRITE set exist
  * > 0: (i_writecount) users are writing to the file.
  *
- * WARNING: as soon as we will move get_write_access(), do_mmap() or
- * prepare_binfmt() out of the big lock we will need a spinlock protecting
- * the checks in all 3. For the time being it is not needed.
+ * Normally we operate on that counter with atomic_{inc,dec} and it's safe
+ * except for the cases where we don't hold i_writecount yet. Then we need to
+ * use {get,deny}_write_access() - these functions check the sign and refuse
+ * to do the change if sign is wrong. Exclusion between them is provided by
+ * spinlock (arbitration_lock) and I'll rip the second arsehole to the first
+ * who will try to move it in struct inode - just leave it here.
  */
+static spinlock_t arbitration_lock = SPIN_LOCK_UNLOCKED;
 int get_write_access(struct inode * inode)
 {
-       if (atomic_read(&inode->i_writecount) < 0)
+       spin_lock(&arbitration_lock);
+       if (atomic_read(&inode->i_writecount) < 0) {
+               spin_unlock(&arbitration_lock);
                return -ETXTBSY;
+       }
        atomic_inc(&inode->i_writecount);
+       spin_unlock(&arbitration_lock);
        return 0;
 }
-
-void put_write_access(struct inode * inode)
+int deny_write_access(struct file * file)
 {
-       atomic_dec(&inode->i_writecount);
+       spin_lock(&arbitration_lock);
+       if (atomic_read(&file->f_dentry->d_inode->i_writecount) > 0) {
+               spin_unlock(&arbitration_lock);
+               return -ETXTBSY;
+       }
+       atomic_dec(&file->f_dentry->d_inode->i_writecount);
+       spin_unlock(&arbitration_lock);
+       return 0;
 }
 
 void path_release(struct nameidata *nd)
@@ -337,7 +357,34 @@ int follow_down(struct vfsmount **mnt, struct dentry **dentry)
 {
        return __follow_down(mnt,dentry);
 }
-
+static inline void follow_dotdot(struct nameidata *nd)
+{
+       while(1) {
+               struct vfsmount *parent;
+               struct dentry *dentry;
+               if (nd->dentry == current->fs->root &&
+                   nd->mnt == current->fs->rootmnt)  {
+                       break;
+               }
+               if (nd->dentry != nd->mnt->mnt_root) {
+                       dentry = dget(nd->dentry->d_parent);
+                       dput(nd->dentry);
+                       nd->dentry = dentry;
+                       break;
+               }
+               parent=nd->mnt->mnt_parent;
+               if (parent == nd->mnt) {
+                       break;
+               }
+               mntget(parent);
+               dentry=dget(nd->mnt->mnt_mountpoint);
+               dput(nd->dentry);
+               nd->dentry = dentry;
+               mntput(nd->mnt);
+               nd->mnt = parent;
+       }
+}
 /*
  * Name resolution.
  *
@@ -403,19 +450,7 @@ int path_walk(const char * name, struct nameidata *nd)
                        case 2: 
                                if (this.name[1] != '.')
                                        break;
-                               while (1) {
-                                       if (nd->dentry == current->fs->root &&
-                                           nd->mnt == current->fs->rootmnt)
-                                               break;
-                                       if (nd->dentry != nd->mnt->mnt_root) {
-                                               dentry = dget(nd->dentry->d_parent);
-                                               dput(nd->dentry);
-                                               nd->dentry = dentry;
-                                               break;
-                                       }
-                                       if (!__follow_up(&nd->mnt, &nd->dentry))
-                                               break;
-                               }
+                               follow_dotdot(nd);
                                inode = nd->dentry->d_inode;
                                /* fallthrough */
                        case 1:
@@ -483,19 +518,7 @@ last_component:
                        case 2: 
                                if (this.name[1] != '.')
                                        break;
-                               while (1) {
-                                       if (nd->dentry == current->fs->root &&
-                                           nd->mnt == current->fs->rootmnt)
-                                               break;
-                                       if (nd->dentry != nd->mnt->mnt_root) {
-                                               dentry = dget(nd->dentry->d_parent);
-                                               dput(nd->dentry);
-                                               nd->dentry = dentry;
-                                               break;
-                                       }
-                                       if (!__follow_up(&nd->mnt, &nd->dentry))
-                                               break;
-                               }
+                               follow_dotdot(nd);
                                inode = nd->dentry->d_inode;
                                /* fallthrough */
                        case 1:
@@ -771,8 +794,6 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
        int error;
        if (!victim->d_inode || victim->d_parent->d_inode != dir)
                return -ENOENT;
-       if (IS_DEADDIR(dir))
-               return -ENOENT;
        error = permission(dir,MAY_WRITE | MAY_EXEC);
        if (error)
                return error;
@@ -786,8 +807,6 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
                        return -ENOTDIR;
                if (IS_ROOT(victim))
                        return -EBUSY;
-               if (d_mountpoint(victim))
-                       return -EBUSY;
        } else if (S_ISDIR(victim->d_inode->i_mode))
                return -EISDIR;
        return 0;
@@ -872,83 +891,92 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
        int acc_mode, error = 0;
        struct inode *inode;
        struct dentry *dentry;
+       struct dentry *dir;
+       int count = 0;
 
        acc_mode = ACC_MODE(flag);
+
+       /*
+        * The simplest case - just a plain lookup.
+        */
        if (!(flag & O_CREAT)) {
                if (path_init(pathname, lookup_flags(flag), nd))
                        error = path_walk(pathname, nd);
                if (error)
                        return error;
-
                dentry = nd->dentry;
-       } else {
-               struct dentry *dir;
+               goto ok;
+       }
 
-               if (path_init(pathname, LOOKUP_PARENT, nd))
-                       error = path_walk(pathname, nd);
+       /*
+        * Create - we need to know the parent.
+        */
+       if (path_init(pathname, LOOKUP_PARENT, nd))
+               error = path_walk(pathname, nd);
+       if (error)
+               return error;
+
+       /*
+        * We have the parent and last component. First of all, check
+        * that we are not asked to creat(2) an obvious directory - that
+        * will not do.
+        */
+       error = -EISDIR;
+       if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])
+               goto exit;
+
+       dir = nd->dentry;
+       down(&dir->d_inode->i_sem);
+       dentry = lookup_hash(&nd->last, nd->dentry);
+
+do_last:
+       error = PTR_ERR(dentry);
+       if (IS_ERR(dentry)) {
+               up(&dir->d_inode->i_sem);
+               goto exit;
+       }
+
+       /* Negative dentry, just create the file */
+       if (!dentry->d_inode) {
+               error = vfs_create(dir->d_inode, dentry, mode);
+               up(&dir->d_inode->i_sem);
+               dput(nd->dentry);
+               nd->dentry = dentry;
                if (error)
-                       return error;
-               /*
-                * It's not obvious that open(".", O_CREAT, foo) should
-                * fail, but it's even less obvious that it should succeed.
-                * Since O_CREAT means an intention to create the thing and
-                * open(2) had never created directories, count it as caller's
-                * luserdom and let him sod off - -EISDIR it is.
-                */
-               error = -EISDIR;
-               if (nd->last_type != LAST_NORM)
-                       goto exit;
-               /* same for foo/ */
-               if (nd->last.name[nd->last.len])
                        goto exit;
+               /* Don't check for write permission, don't truncate */
+               acc_mode = 0;
+               flag &= ~O_TRUNC;
+               goto ok;
+       }
 
-               dir = nd->dentry;
-               down(&dir->d_inode->i_sem);
+       /*
+        * It already exists.
+        */
+       up(&dir->d_inode->i_sem);
 
-               dentry = lookup_hash(&nd->last, nd->dentry);
-               error = PTR_ERR(dentry);
-               if (IS_ERR(dentry)) {
-                       up(&dir->d_inode->i_sem);
-                       goto exit;
-               }
+       error = -EEXIST;
+       if (flag & O_EXCL)
+               goto exit_dput;
 
-               if (dentry->d_inode) {
-                       up(&dir->d_inode->i_sem);
-                       error = -EEXIST;
-                       if (flag & O_EXCL)
-                               goto exit_dput;
-                       if (dentry->d_inode->i_op &&
-                           dentry->d_inode->i_op->follow_link) {
-                               /*
-                                * With O_EXCL it would be -EEXIST.
-                                * If symlink is a dangling one it's -ENOENT.
-                                * Otherwise we open the object it points to.
-                                */
-                               error = do_follow_link(dentry, nd);
-                               dput(dentry);
-                               if (error)
-                                       return error;
-                               dentry = nd->dentry;
-                       } else {
-                               dput(nd->dentry);
-                               nd->dentry = dentry;
-                       }
-                       error = -EISDIR;
-                       if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
-                               goto exit;
-               } else {
-                       error = vfs_create(dir->d_inode, dentry, mode);
-                       up(&dir->d_inode->i_sem);
-                       /* Don't check for write permission, don't truncate */
-                       acc_mode = 0;
-                       flag &= ~O_TRUNC;
-                       dput(nd->dentry);
-                       nd->dentry = dentry;
-                       if (error)
-                               goto exit;
-               }
+       if (d_mountpoint(dentry)) {
+               error = -ELOOP;
+               if (flag & O_NOFOLLOW)
+                       goto exit_dput;
+               do __follow_down(&nd->mnt,&dentry); while(d_mountpoint(dentry));
        }
+       error = -ENOENT;
+       if (!dentry->d_inode)
+               goto exit_dput;
+       if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
+               goto do_link;
 
+       dput(nd->dentry);
+       nd->dentry = dentry;
+       error = -EISDIR;
+       if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
+               goto exit;
+ok:
        error = -ENOENT;
        inode = dentry->d_inode;
        if (!inode)
@@ -1023,6 +1051,47 @@ exit_dput:
 exit:
        path_release(nd);
        return error;
+
+do_link:
+       error = -ELOOP;
+       if (flag & O_NOFOLLOW)
+               goto exit_dput;
+       /*
+        * This is subtle. Instead of calling do_follow_link() we do the
+        * thing by hands. The reason is that this way we have zero link_count
+        * and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT.
+        * After that we have the parent and last component, i.e.
+        * we are in the same situation as after the first path_walk().
+        * Well, almost - if the last component is normal we get its copy
+        * stored in nd->last.name and we will have to putname() it when we
+        * are done. Procfs-like symlinks just set LAST_BIND.
+        */
+       UPDATE_ATIME(dentry->d_inode);
+       error = dentry->d_inode->i_op->follow_link(dentry, nd);
+       dput(dentry);
+       if (error)
+               return error;
+       if (nd->last_type == LAST_BIND) {
+               dentry = nd->dentry;
+               goto ok;
+       }
+       error = -EISDIR;
+       if (nd->last_type != LAST_NORM)
+               goto exit;
+       if (nd->last.name[nd->last.len]) {
+               putname(nd->last.name);
+               goto exit;
+       }
+       if (count++==32) {
+               dentry = nd->dentry;
+               putname(nd->last.name);
+               goto ok;
+       }
+       dir = nd->dentry;
+       down(&dir->d_inode->i_sem);
+       dentry = lookup_hash(&nd->last, nd->dentry);
+       putname(nd->last.name);
+       goto do_last;
 }
 
 static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
@@ -1213,9 +1282,15 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
 
        double_down(&dir->i_zombie, &dentry->d_inode->i_zombie);
        d_unhash(dentry);
-       error = dir->i_op->rmdir(dir, dentry);
-       if (!error)
-               dentry->d_inode->i_flags |= S_DEAD;
+       if (IS_DEADDIR(dir))
+               error = -ENOENT;
+       else if (d_mountpoint(dentry))
+               error = -EBUSY;
+       else {
+               error = dir->i_op->rmdir(dir, dentry);
+               if (!error)
+                       dentry->d_inode->i_flags |= S_DEAD;
+       }
        double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
        if (!error)
                d_delete(dentry);
@@ -1275,9 +1350,13 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
                error = -EPERM;
                if (dir->i_op && dir->i_op->unlink) {
                        DQUOT_INIT(dir);
-                       error = dir->i_op->unlink(dir, dentry);
-                       if (!error)
-                               d_delete(dentry);
+                       if (d_mountpoint(dentry))
+                               error = -EBUSY;
+                       else {
+                               error = dir->i_op->unlink(dir, dentry);
+                               if (!error)
+                                       d_delete(dentry);
+                       }
                }
        }
        up(&dir->i_zombie);
@@ -1555,7 +1634,12 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
        } else
                double_down(&old_dir->i_zombie,
                            &new_dir->i_zombie);
-       error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+       if (IS_DEADDIR(old_dir)||IS_DEADDIR(new_dir))
+               error = -ENOENT;
+       else if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
+               error = -EBUSY;
+       else 
+               error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
        if (target) {
                if (!error)
                        target->i_flags |= S_DEAD;
@@ -1603,7 +1687,10 @@ int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
        DQUOT_INIT(old_dir);
        DQUOT_INIT(new_dir);
        double_down(&old_dir->i_zombie, &new_dir->i_zombie);
-       error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+       if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
+               error = -EBUSY;
+       else
+               error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
        double_up(&old_dir->i_zombie, &new_dir->i_zombie);
        if (error)
                return error;
@@ -1734,6 +1821,8 @@ out:
 static inline int
 __vfs_follow_link(struct nameidata *nd, const char *link)
 {
+       int res = 0;
+       char *name;
        if (IS_ERR(link))
                goto fail;
 
@@ -1741,10 +1830,25 @@ __vfs_follow_link(struct nameidata *nd, const char *link)
                path_release(nd);
                if (!walk_init_root(link, nd))
                        /* weird __emul_prefix() stuff did it */
-                       return 0;
+                       goto out;
        }
-       return path_walk(link, nd);
-
+       res = path_walk(link, nd);
+out:
+       if (current->link_count || res || nd->last_type!=LAST_NORM)
+               return res;
+       /*
+        * If it is an iterative symlinks resolution in open_namei() we
+        * have to copy the last component. And all that crap because of
+        * bloody create() on broken symlinks. Furrfu...
+        */
+       name = __getname();
+       if (IS_ERR(name))
+               goto fail_name;
+       strcpy(name, nd->last.name);
+       nd->last.name = name;
+       return 0;
+fail_name:
+       link = name;
 fail:
        path_release(nd);
        return PTR_ERR(link);
index dee52dd8afc7b08ed58de04d83f0a2adfc6d0ac8..df25320488140aac4f4087ec6644e17180e4529c 100644 (file)
@@ -9,8 +9,6 @@
  * creates a client control block and adds it to the hash
  * table. Then, you call NFSCTL_EXPORT for each fs.
  *
- * You cannot currently read the export information from the
- * kernel. It would be nice to have a /proc file though.
  *
  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
  */
@@ -388,12 +386,10 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
 
        err = -EPERM;
        if (path) {
-               err = 0;
-               if (path_init(path, LOOKUP_POSITIVE, &nd))
-                       err = path_walk(path, &nd);
-               if (err) {
+               if (path_init(path, LOOKUP_POSITIVE, &nd) &&
+                   path_walk(path, &nd)) {
                        printk("nfsd: exp_rootfh path not found %s", path);
-                       return -EPERM;
+                       return err;
                }
                dev = nd.dentry->d_inode->i_dev;
                ino = nd.dentry->d_inode->i_ino;
@@ -438,7 +434,8 @@ exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
        fh_put(&fh);
 
 out:
-       path_release(&nd);
+       if (path)
+               path_release(&nd);
        return err;
 }
 
index 357a297f66481662fb022bafb522a291234c1aca..f5795583bd8cea0977b3b7fbee2f742196490537 100644 (file)
@@ -174,8 +174,9 @@ int
 nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
 {
        struct svc_cacherep     *rh, *rp;
-       struct svc_client       *clp = rqstp->rq_client;
        u32                     xid = rqstp->rq_xid,
+                               proto =  rqstp->rq_prot,
+                               vers = rqstp->rq_vers,
                                proc = rqstp->rq_proc;
        unsigned long           age;
 
@@ -189,7 +190,9 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
        while ((rp = rp->c_hash_next) != rh) {
                if (rp->c_state != RC_UNUSED &&
                    xid == rp->c_xid && proc == rp->c_proc &&
-                   exp_checkaddr(clp, rp->c_client)) {
+                   proto == rp->c_prot && vers == rp->c_vers &&
+                   time_before(jiffies, rp->c_timestamp + 120*HZ) &&
+                   memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, rqstp->rq_addrlen)==0) {
                        nfsdstats.rchits++;
                        goto found_entry;
                }
@@ -226,7 +229,11 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
        rp->c_state = RC_INPROG;
        rp->c_xid = xid;
        rp->c_proc = proc;
-       rp->c_client = rqstp->rq_addr.sin_addr;
+       rp->c_addr = rqstp->rq_addr;
+       rp->c_prot = proto;
+       rp->c_vers = vers;
+       rp->c_timestamp = jiffies;
+
        hash_refile(rp);
 
        /* release any buffer */
index c4e4561859a5d36871ea326795b7560ba23498e0..913cbf5f8e7d941b6c87288a44cb7a476762b516 100644 (file)
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  */
-#define NFS_GETFH_NEW
 
 #include <linux/config.h>
 #include <linux/module.h>
index 85a98c8740701a90a672c008e46b7f326886274c..78f399bd37b075ede1e8c40629beb00670e3502a 100644 (file)
@@ -495,17 +495,15 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 
        dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
 
-       if (!fhp->fh_dverified) {
+       if (!fhp->fh_dentry) {
                kdev_t xdev;
                ino_t xino;
                __u32 *datap=NULL;
                int data_left = fh->fh_size/4;
                int nfsdev;
                error = nfserr_stale;
-#if CONFIG_NFSD_V3             
                if (rqstp->rq_vers == 3)
                        error = nfserr_badhandle;
-#endif
                if (fh->fh_version == 1) {
                        
                        datap = fh->fh_auth;
@@ -562,10 +560,8 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
                 * Look up the dentry using the NFS file handle.
                 */
                error = nfserr_stale;
-#if CONFIG_NFSD_V3             
                if (rqstp->rq_vers == 3)
                        error = nfserr_badhandle;
-#endif
 
                if (fh->fh_version == 1) {
                        /* if fileid_type != 0, and super_operations provide fh_to_dentry lookup,
@@ -611,7 +607,6 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
 
                fhp->fh_dentry = dentry;
                fhp->fh_export = exp;
-               fhp->fh_dverified = 1;
                nfsd_nr_verified++;
        } else {
                /* just rechecking permissions
@@ -731,7 +726,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
                parent->d_name.name, dentry->d_name.name,
                (inode ? inode->i_ino : 0));
 
-       if (fhp->fh_dverified || fhp->fh_locked || fhp->fh_dentry) {
+       if (fhp->fh_locked || fhp->fh_dentry) {
                printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
                        parent->d_name.name, dentry->d_name.name);
        }
@@ -757,8 +752,6 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry)
        fhp->fh_handle.fh_size = (datap-fhp->fh_handle.fh_auth+1)*4;
 
 
-       /* We stuck it there, we know it's good. */
-       fhp->fh_dverified = 1;
        nfsd_nr_verified++;
        if (fhp->fh_handle.fh_fileid_type == 255)
                return nfserr_opnotsupp;
@@ -775,7 +768,7 @@ fh_update(struct svc_fh *fhp)
        struct dentry *dentry;
        __u32 *datap;
        
-       if (!fhp->fh_dverified)
+       if (!fhp->fh_dentry)
                goto out_bad;
 
        dentry = fhp->fh_dentry;
@@ -811,10 +804,9 @@ void
 fh_put(struct svc_fh *fhp)
 {
        struct dentry * dentry = fhp->fh_dentry;
-       if (fhp->fh_dverified) {
+       if (dentry) {
                fh_unlock(fhp);
                fhp->fh_dentry = NULL;
-               fhp->fh_dverified = 0;
                dput(dentry);
                nfsd_nr_put++;
        }
index 763970736e50ddbc44a9304d80dc1ead0ae172c8..b5057d57b5f4d9ae2f306c5ebb3fd8d6d61efaf2 100644 (file)
@@ -239,7 +239,7 @@ nfsd_proc_create(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
                 * whether the file exists or not. Time to bail ...
                 */
                nfserr = nfserr_acces;
-               if (!newfhp->fh_dverified) {
+               if (!newfhp->fh_dentry) {
                        printk(KERN_WARNING 
                                "nfsd_proc_create: file handle not verified\n");
                        goto out_unlock;
@@ -415,7 +415,7 @@ nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp,
 
        dprintk("nfsd: MKDIR    %s %s\n", SVCFH_fmt(&argp->fh), argp->name);
 
-       if (resp->fh.fh_dverified) {
+       if (resp->fh.fh_dentry) {
                printk(KERN_WARNING
                        "nfsd_proc_mkdir: response already verified??\n");
        }
index fb3b32f8de56e74d570abfa8034a0964ecf7f4a9..9a4d12a7d244bcf677a6ce1abd0fd5b110f85ae2 100644 (file)
@@ -275,7 +275,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
        /* Encode result.
         * For NFSv2, additional info is never returned in case of an error.
         */
-#ifdef CONFIG_NFSD_V3
        if (!(nfserr && rqstp->rq_vers == 2)) {
                xdr = proc->pc_encode;
                if (xdr && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
@@ -286,17 +285,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
                        return 1;
                }
        }
-#else
-       xdr = proc->pc_encode;
-       if (!nfserr && xdr
-        && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
-               /* Failed to encode result. Release cache entry */
-               dprintk("nfsd: failed to encode result!\n");
-               nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
-               *statp = rpc_system_err;
-               return 1;
-       }
-#endif /* CONFIG_NFSD_V3 */
 
        /* Store reply in cache. */
        nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1);
index 40f1ab85aa2ccdf3920ddca1c25f920f4671c0f1..79bceeb860c2e656bd1a233d29c3ded3f0a90e77 100644 (file)
@@ -165,6 +165,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
                                dentry = mounts;
                        } else
                                dput(mounts);
+                       mntput(mnt);
                }
        }
        /*
@@ -253,8 +254,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
                        goto out_nfserr;
 
                err = locks_verify_truncate(inode, NULL, iap->ia_size);
-               if (err)
+               if (err) {
+                       put_write_access(inode);
                        goto out_nfserr;
+               }
                DQUOT_INIT(inode);
        }
 
@@ -316,9 +319,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
        if (EX_ISSYNC(fhp->fh_export))
                write_inode_now(inode);
        err = 0;
-
-       /* Don't unlock inode; the nfssvc_release functions are supposed
-        * to do this. */
 out:
        return err;
 
@@ -413,7 +413,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
  out:
        return error;
 }
-#endif
+#endif /* CONFIG_NFSD_V3 */
 
 
 
@@ -598,7 +598,6 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        oldfs = get_fs(); set_fs(KERNEL_DS);
        err = file.f_op->read(&file, buf, *count, &file.f_pos);
        set_fs(oldfs);
-       nfsdstats.io_read += *count;
 
        /* Write back readahead params */
        if (ra != NULL) {
@@ -614,6 +613,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        }
 
        if (err >= 0) {
+               nfsdstats.io_read += err;
                *count = err;
                err = 0;
        } else 
@@ -665,19 +665,16 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
         * When gathered writes have been configured for this volume,
         * flushing the data to disk is handled separately below.
         */
-#ifdef CONFIG_NFSD_V3
+
        if (file.f_op->fsync == 0) {/* COMMIT3 cannot work */
               stable = 2;
               *stablep = 2; /* FILE_SYNC */
        }
+
        if (!EX_ISSYNC(exp))
                stable = 0;
        if (stable && !EX_WGATHER(exp))
                file.f_flags |= O_SYNC;
-#else
-       if ((stable || (stable = EX_ISSYNC(exp))) && !EX_WGATHER(exp))
-               file.f_flags |= O_SYNC;
-#endif /* CONFIG_NFSD_V3 */
 
        file.f_pos = offset;            /* set write offset */
 
@@ -692,7 +689,8 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 #else
        err = file.f_op->write(&file, buf, cnt, &file.f_pos);
 #endif
-       nfsdstats.io_write += cnt;
+       if (err >= 0)
+               nfsdstats.io_write += cnt;
        set_fs(oldfs);
 
        /* clear setuid/setgid flag after write */
@@ -734,7 +732,9 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
 #else
                        dprintk("nfsd: write defer %d\n", current->pid);
 /* FIXME: Olaf commented this out [gam3] */
+                       set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout((HZ+99)/100);
+                       current->state = TASK_RUNNING;
                        dprintk("nfsd: write resume %d\n", current->pid);
 #endif
                }
@@ -743,7 +743,9 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
                        dprintk("nfsd: write sync %d\n", current->pid);
                        nfsd_sync(&file);
                }
+#if 0
                wake_up(&inode->i_wait);
+#endif
                last_ino = inode->i_ino;
                last_dev = inode->i_dev;
        }
@@ -762,11 +764,12 @@ out:
 
 #ifdef CONFIG_NFSD_V3
 /*
- * Commit all pendig writes to stable storage.
- * Strictly speaking, we could sync just indicated the file region here,
+ * Commit all pending writes to stable storage.
+ * Strictly speaking, we could sync just the indicated file region here,
  * but there's currently no way we can ask the VFS to do so.
  *
- * We lock the file to make sure we return full WCC data to the client.
+ * Unfortunately we cannot lock the file to make sure we return full WCC
+ * data to the client, as locking happens lower down in the filesystem.
  */
 int
 nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
@@ -828,7 +831,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
         * Check whether the response file handle has been verified yet.
         * If it has, the parent directory should already be locked.
         */
-       if (!resfhp->fh_dverified) {
+       if (!resfhp->fh_dentry) {
                /* called from nfsd_proc_mkdir, or possibly nfsd3_proc_create */
                fh_lock(fhp);
                dchild = lookup_one(fname, dentry);
@@ -928,6 +931,8 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        struct dentry   *dentry, *dchild;
        struct inode    *dirp;
        int             err;
+       __u32           v_mtime=0, v_atime=0;
+       int             v_mode=0;
 
        err = nfserr_perm;
        if (!flen)
@@ -963,6 +968,19 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (err)
                goto out;
 
+       if (createmode == NFS3_CREATE_EXCLUSIVE) {
+               /* while the verifier would fit in mtime+atime,
+                * solaris7 gets confused (bugid 4218508) if these have
+                * the high bit set, so we use the mode as well
+                */
+               v_mtime = verifier[0]&0x7fffffff;
+               v_atime = verifier[1]&0x7fffffff;
+               v_mode  = S_IFREG
+                       | ((verifier[0]&0x80000000) >> (32-7)) /* u+x */
+                       | ((verifier[1]&0x80000000) >> (32-9)) /* u+r */
+                       ;
+       }
+       
        if (dchild->d_inode) {
                err = 0;
 
@@ -976,10 +994,10 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                        }
                        break;
                case NFS3_CREATE_EXCLUSIVE:
-                       if (   dchild->d_inode->i_mtime == verifier[0]
-                           && dchild->d_inode->i_atime == verifier[1]
-                           && dchild->d_inode->i_mode == S_IFREG
-                           && dchild->d_inode->i_size == 0 )
+                       if (   dchild->d_inode->i_mtime == v_mtime
+                           && dchild->d_inode->i_atime == v_atime
+                           && dchild->d_inode->i_mode  == v_mode
+                           && dchild->d_inode->i_size  == 0 )
                                break;
                         /* fallthru */
                case NFS3_CREATE_GUARDED:
@@ -1005,19 +1023,23 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
 
        if (createmode == NFS3_CREATE_EXCLUSIVE) {
-               /* Cram the verifier into atime/mtime */
-               iap->ia_valid = ATTR_MTIME|ATTR_ATIME|ATTR_MTIME_SET|ATTR_ATIME_SET;
-               iap->ia_mtime = verifier[0];
-               iap->ia_atime = verifier[1];
+               /* Cram the verifier into atime/mtime/mode */
+               iap->ia_valid = ATTR_MTIME|ATTR_ATIME
+                       | ATTR_MTIME_SET|ATTR_ATIME_SET
+                       | ATTR_MODE;
+               iap->ia_mtime = v_mtime;
+               iap->ia_atime = v_atime;
+               iap->ia_mode  = v_mode;
        }
 
-       /* Set file attributes. Mode has already been set and
-        * setting uid/gid works only for root. Irix appears to
-        * send along the gid when it tries to implement setgid
-        * directories via NFS. Clear out all that cruft.
+       /* Set file attributes.
+        * Mode has already been set but we might need to reset it
+        * for CREATE_EXCLUSIVE
+        * Irix appears to send along the gid when it tries to
+        * implement setgid directories via NFS. Clear out all that cruft.
         */
  set_attr:
-       if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID|ATTR_MODE)) != 0)
+       if ((iap->ia_valid &= ~(ATTR_UID|ATTR_GID)) != 0)
                err = nfsd_setattr(rqstp, resfhp, iap);
 
  out:
@@ -1230,7 +1252,13 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
        if (!flen || isdotent(fname, flen) || !tlen || isdotent(tname, tlen))
                goto out;
 
+       /* cannot use fh_lock as we need deadlock protective ordering
+        * so do it by hand */
        double_down(&tdir->i_sem, &fdir->i_sem);
+       ffhp->fh_locked = tfhp->fh_locked = 1;
+       fill_pre_wcc(ffhp);
+       fill_pre_wcc(tfhp);
+
        odentry = lookup_one(fname, fdentry);
        err = PTR_ERR(odentry);
        if (IS_ERR(odentry))
@@ -1245,39 +1273,31 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
        if (IS_ERR(ndentry))
                goto out_dput_old;
 
-#ifdef CONFIG_NFSD_V3
-       /* Fill in the pre-op attr for the wcc data for both 
-        * tdir and fdir
-        */ 
-       fill_pre_wcc(ffhp);
-       fill_pre_wcc(tfhp);
-#endif /* CONFIG_NFSD_V3 */
 
        err = vfs_rename(fdir, odentry, tdir, ndentry);
        if (!err && EX_ISSYNC(tfhp->fh_export)) {
                nfsd_sync_dir(tdentry);
                nfsd_sync_dir(fdentry);
        }
-#ifdef CONFIG_NFSD_V3
-        /* Fill in the post-op attr for the wcc data for both 
-         * tdir and fdir
-         */
-       fill_post_wcc(ffhp);
-       fill_post_wcc(tfhp);
-#endif /* CONFIG_NFSD_V3 */
-       double_up(&tdir->i_sem, &fdir->i_sem);
        dput(ndentry);
 
-out_dput_old:
+ out_dput_old:
        dput(odentry);
+ out_nfserr:
        if (err)
-               goto out_nfserr;
+               err = nfserrno(err);
+
+       /* we cannot reply on fh_unlock on the two filehandles,
+        * as that would do the wrong thing if the two directories
+        * were the same, so again we do it by hand
+        */
+       fill_post_wcc(ffhp);
+       fill_post_wcc(tfhp);
+       double_up(&tdir->i_sem, &fdir->i_sem);
+       ffhp->fh_locked = tfhp->fh_locked = 0;
+       
 out:
        return err;
-
-out_nfserr:
-       err = nfserrno(err);
-       goto out;
 }
 
 /*
@@ -1320,17 +1340,13 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
                err = vfs_rmdir(dirp, rdentry);
        }
 
-       fh_unlock(fhp);
-
        dput(rdentry);
 
        if (err)
                goto out_nfserr;
-       if (EX_ISSYNC(fhp->fh_export)) {
-               down(&dentry->d_inode->i_sem);
+       if (EX_ISSYNC(fhp->fh_export)) 
                nfsd_sync_dir(dentry);
-               up(&dentry->d_inode->i_sem);
-       }
+
 out:
        return err;
 
@@ -1353,13 +1369,11 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        struct file     file;
        struct readdir_cd cd;
 
-       err = 0;
-       if (offset > ~(u32) 0)
-               goto out;
-
        err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
        if (err)
                goto out;
+       if (offset > ~(u32) 0)
+               goto out_close;
 
        err = nfserr_notdir;
        if (!file.f_op->readdir)
@@ -1402,11 +1416,9 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
        eof = !cd.eob;
 
        if (cd.offset) {
-#ifdef CONFIG_NFSD_V3
                if (rqstp->rq_vers == 3)
                        (void)xdr_encode_hyper(cd.offset, file.f_pos);
                else
-#endif /* CONFIG_NFSD_V3 */
                        *cd.offset = htonl(file.f_pos);
        }
 
index b97851fab7beed9a7024a08a3bb4375b85bc0d3d..a30985a538bac83b7f6ecb6c71f07b83517105da 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -607,6 +607,8 @@ static struct super_block * pipefs_read_super(struct super_block *sb, void *data
        root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
        root->i_uid = root->i_gid = 0;
        root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
+       root->i_sb = sb;
+       root->i_dev = sb->s_dev;
        sb->s_blocksize = 1024;
        sb->s_blocksize_bits = 10;
        sb->s_magic = PIPEFS_MAGIC;
index fb63722d523a1f64117adcec0f6a18f009a2e701..383ef6019ef2ed3be5b1108526cc5de7dff555a4 100644 (file)
@@ -408,6 +408,7 @@ static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
                goto out;
 
        error = inode->u.proc_i.op.proc_get_link(inode, &nd->dentry, &nd->mnt);
+       nd->last_type = LAST_BIND;
 out:
 #ifdef NULL_VFSMNT
        mntput(dummy);
index 60393eb91a2c58d06a377a6bced4f17b5e3d1e5f..3576482ca1a5ed65e88fd4f60ff1e3693428636d 100644 (file)
@@ -340,7 +340,6 @@ static struct super_block *qnx4_read_super(struct super_block *s,
        set_blocksize(dev, QNX4_BLOCK_SIZE);
        s->s_blocksize = QNX4_BLOCK_SIZE;
        s->s_blocksize_bits = QNX4_BLOCK_SIZE_BITS;
-       s->s_dev = dev;
 
        /* Check the boot signature. Since the qnx4 code is
           dangerous, we should leave as quickly as possible
index 5b8974e5b0ef37722899b492d7a206c84557cea7..cfc5c90613bfb4ed606a19fc571323b0bdb65eac 100644 (file)
@@ -260,7 +260,7 @@ int get_filesystem_list(char * buf)
        return len;
 }
 
-static struct file_system_type *get_fs_type(const char *name)
+struct file_system_type *get_fs_type(const char *name)
 {
        struct file_system_type *fs;
        
@@ -281,14 +281,28 @@ static struct file_system_type *get_fs_type(const char *name)
 
 static LIST_HEAD(vfsmntlist);
 
-static struct vfsmount *add_vfsmnt(struct super_block *sb,
-                               struct dentry *mountpoint,
+/**
+ *     add_vfsmnt - add a new mount node
+ *     @nd: location of mountpoint or %NULL if we want a root node
+ *     @root: root of (sub)tree to be mounted
+ *     @dev_name: device name to show in /proc/mounts
+ *
+ *     This is VFS idea of mount. New node is allocated, bound to a tree
+ *     we are mounting and optionally (OK, usually) registered as mounted
+ *     on a given mountpoint. Returns a pointer to new node or %NULL in
+ *     case of failure.
+ *
+ *     Potential reason for failure (aside of trivial lack of memory) is a
+ *     deleted mountpoint. Caller must hold ->i_zombie on mountpoint
+ *     dentry (if any).
+ */
+
+static struct vfsmount *add_vfsmnt(struct nameidata *nd,
                                struct dentry *root,
-                               struct vfsmount *parent,
-                               const char *dev_name,
-                               const char *dir_name)
+                               const char *dev_name)
 {
        struct vfsmount *mnt;
+       struct super_block *sb = root->d_inode->i_sb;
        char *name;
 
        mnt = kmalloc(sizeof(struct vfsmount), GFP_KERNEL);
@@ -296,13 +310,7 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb,
                goto out;
        memset(mnt, 0, sizeof(struct vfsmount));
 
-       atomic_set(&mnt->mnt_count,1);
-       mnt->mnt_sb = sb;
-       mnt->mnt_mountpoint = dget(mountpoint);
-       mnt->mnt_root = dget(root);
-       mnt->mnt_parent = parent ? mntget(parent) : mnt;
-
-       /* N.B. Is it really OK to have a vfsmount without names? */
+       /* It may be NULL, but who cares? */
        if (dev_name) {
                name = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
                if (name) {
@@ -310,51 +318,53 @@ static struct vfsmount *add_vfsmnt(struct super_block *sb,
                        mnt->mnt_devname = name;
                }
        }
-       name = kmalloc(strlen(dir_name)+1, GFP_KERNEL);
-       if (name) {
-               strcpy(name, dir_name);
-               mnt->mnt_dirname = name;
-       }
        mnt->mnt_owner = current->uid;
+       atomic_set(&mnt->mnt_count,1);
+       mnt->mnt_sb = sb;
 
-       if (parent)
-               list_add(&mnt->mnt_child, &parent->mnt_mounts);
-       else
+       if (nd && !IS_ROOT(nd->dentry) && d_unhashed(nd->dentry))
+               goto fail;
+       mnt->mnt_root = dget(root);
+       mnt->mnt_mountpoint = nd ? dget(nd->dentry) : dget(root);
+       mnt->mnt_parent = nd ? mntget(nd->mnt) : mnt;
+
+       if (nd) {
+               list_add(&mnt->mnt_child, &nd->mnt->mnt_mounts);
+               list_add(&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
+       } else {
                INIT_LIST_HEAD(&mnt->mnt_child);
+               INIT_LIST_HEAD(&mnt->mnt_clash);
+       }
        INIT_LIST_HEAD(&mnt->mnt_mounts);
        list_add(&mnt->mnt_instances, &sb->s_mounts);
-       list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt);
        list_add(&mnt->mnt_list, vfsmntlist.prev);
 out:
        return mnt;
+fail:
+       kfree(mnt->mnt_devname);
+       kfree(mnt);
+       return NULL;
 }
 
 static void move_vfsmnt(struct vfsmount *mnt,
                        struct dentry *mountpoint,
                        struct vfsmount *parent,
-                       const char *dev_name,
-                       const char *dir_name)
+                       const char *dev_name)
 {
-       struct dentry *old_mountpoint = mnt->mnt_mountpoint;
-       struct vfsmount *old_parent = mnt->mnt_parent;
-       char *new_devname = NULL, *new_dirname = NULL;
+       struct dentry *old_mountpoint;
+       struct vfsmount *old_parent;
+       char *new_devname = NULL;
 
        if (dev_name) {
                new_devname = kmalloc(strlen(dev_name)+1, GFP_KERNEL);
                if (new_devname)
                        strcpy(new_devname, dev_name);
        }
-       if (dir_name) {
-               new_dirname = kmalloc(strlen(dir_name)+1, GFP_KERNEL);
-               if (new_dirname)
-                       strcpy(new_dirname, dir_name);
-       }
+
+       old_mountpoint = mnt->mnt_mountpoint;
+       old_parent = mnt->mnt_parent;
 
        /* flip names */
-       if (new_dirname) {
-               kfree(mnt->mnt_dirname);
-               mnt->mnt_dirname = new_dirname;
-       }
        if (new_devname) {
                kfree(mnt->mnt_devname);
                mnt->mnt_devname = new_devname;
@@ -365,11 +375,13 @@ static void move_vfsmnt(struct vfsmount *mnt,
        mnt->mnt_parent = parent ? mntget(parent) : mnt;
        list_del(&mnt->mnt_clash);
        list_del(&mnt->mnt_child);
-       list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt);
-       if (parent)
+       if (parent) {
                list_add(&mnt->mnt_child, &parent->mnt_mounts);
-       else
+               list_add(&mnt->mnt_clash, &mountpoint->d_vfsmnt);
+       } else {
                INIT_LIST_HEAD(&mnt->mnt_child);
+               INIT_LIST_HEAD(&mnt->mnt_clash);
+       }
 
        /* put the old stuff */
        dput(old_mountpoint);
@@ -391,7 +403,6 @@ static void remove_vfsmnt(struct vfsmount *mnt)
        dput(mnt->mnt_mountpoint);
        dput(mnt->mnt_root);
        kfree(mnt->mnt_devname);
-       kfree(mnt->mnt_dirname);
        kfree(mnt);
 }
 
@@ -738,10 +749,6 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
        /* Done with lookups, semaphore down */
        down(&mount_sem);
        dev = to_kdev_t(bdev->bd_dev);
-       check_disk_change(dev);
-       error = -EACCES;
-       if (!(flags & MS_RDONLY) && is_read_only(dev))
-               goto out;
        sb = get_super(dev);
        if (sb) {
                if (fs_type == sb->s_type) {
@@ -755,6 +762,10 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
                error = blkdev_get(bdev, mode, 0, BDEV_FS);
                if (error)
                        goto out;
+               check_disk_change(dev);
+               error = -EACCES;
+               if (!(flags & MS_RDONLY) && is_read_only(dev))
+                       goto out1;
                error = -EINVAL;
                sb = read_super(dev, bdev, fs_type, flags, data, 0);
                if (sb) {
@@ -762,6 +773,7 @@ static struct super_block *get_sb_bdev(struct file_system_type *fs_type,
                        path_release(&nd);
                        return sb;
                }
+out1:
                blkdev_put(bdev, BDEV_FS);
        }
 out:
@@ -895,7 +907,7 @@ struct vfsmount *kern_mount(struct file_system_type *type)
                put_unnamed_dev(dev);
                return ERR_PTR(-EINVAL);
        }
-       mnt = add_vfsmnt(sb, sb->s_root, sb->s_root, NULL, "none", type->name);
+       mnt = add_vfsmnt(NULL, sb->s_root, "none");
        if (!mnt) {
                kill_super(sb, 0);
                return ERR_PTR(-ENOMEM);
@@ -909,10 +921,7 @@ struct vfsmount *kern_mount(struct file_system_type *type)
 void kern_umount(struct vfsmount *mnt)
 {
        struct super_block *sb = mnt->mnt_sb;
-       struct dentry *root = sb->s_root;
        remove_vfsmnt(mnt);
-       dput(root);
-       sb->s_root = NULL;
        kill_super(sb, 0);
 }
 
@@ -932,6 +941,16 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
 {
        struct super_block * sb = mnt->mnt_sb;
 
+       /*
+        * No sense to grab the lock for this test, but test itself looks
+        * somewhat bogus. Suggestions for better replacement?
+        * Ho-hum... In principle, we might treat that as umount + switch
+        * to rootfs. GC would eventually take care of the old vfsmount.
+        * The problem being: we have to implement rootfs and GC for that ;-)
+        * Actually it makes sense, especially if rootfs would contain a
+        * /reboot - static binary that would close all descriptors and
+        * call reboot(9). Then init(8) could umount root and exec /reboot.
+        */
        if (mnt == current->fs->rootmnt && !umount_root) {
                int retval = 0;
                /*
@@ -952,6 +971,7 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
        if (mnt->mnt_instances.next != mnt->mnt_instances.prev) {
                if (sb->s_type->fs_flags & FS_SINGLE)
                        put_filesystem(sb->s_type);
+               /* We hold two references, so mntput() is safe */
                mntput(mnt);
                remove_vfsmnt(mnt);
                return 0;
@@ -988,14 +1008,14 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
        shrink_dcache_sb(sb);
        fsync_dev(sb->s_dev);
 
-       /* Something might grab it again - redo checks */
-
-       if (atomic_read(&mnt->mnt_count) > 2) {
+       if (sb->s_root->d_inode->i_state) {
                mntput(mnt);
                return -EBUSY;
        }
 
-       if (sb->s_root->d_inode->i_state) {
+       /* Something might grab it again - redo checks */
+
+       if (atomic_read(&mnt->mnt_count) > 2) {
                mntput(mnt);
                return -EBUSY;
        }
@@ -1067,6 +1087,8 @@ static int mount_is_safe(struct nameidata *nd)
 {
        if (capable(CAP_SYS_ADMIN))
                return 0;
+       return -EPERM;
+#ifdef notyet
        if (S_ISLNK(nd->dentry->d_inode->i_mode))
                return -EPERM;
        if (nd->dentry->d_inode->i_mode & S_ISVTX) {
@@ -1076,6 +1098,7 @@ static int mount_is_safe(struct nameidata *nd)
        if (permission(nd->dentry->d_inode, MAY_WRITE))
                return -EPERM;
        return 0;
+#endif
 }
 
 /*
@@ -1102,22 +1125,22 @@ static int do_loopback(char *old_name, char *new_name)
        if (S_ISDIR(new_nd.dentry->d_inode->i_mode) !=
              S_ISDIR(old_nd.dentry->d_inode->i_mode))
                goto out2;
-               
-       down(&mount_sem);
-       err = -ENOENT;
-       if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
-               goto out3;
-       if (d_unhashed(new_nd.dentry) && !IS_ROOT(new_nd.dentry))
-               goto out3;
-       /* there we go */
+
        err = -ENOMEM;
        if (old_nd.mnt->mnt_sb->s_type->fs_flags & FS_SINGLE)
                get_filesystem(old_nd.mnt->mnt_sb->s_type);
-       if (add_vfsmnt(old_nd.mnt->mnt_sb, new_nd.dentry, old_nd.dentry,
-                      new_nd.mnt, old_nd.mnt->mnt_devname, new_name))
+               
+       down(&mount_sem);
+       /* there we go */
+       down(&new_nd.dentry->d_inode->i_zombie);
+       if (IS_DEADDIR(new_nd.dentry->d_inode))
+               err = -ENOENT;
+       else if (add_vfsmnt(&new_nd, old_nd.dentry, old_nd.mnt->mnt_devname))
                err = 0;
-out3:
+       up(&new_nd.dentry->d_inode->i_zombie);
        up(&mount_sem);
+       if (err && old_nd.mnt->mnt_sb->s_type->fs_flags & FS_SINGLE)
+               put_filesystem(old_nd.mnt->mnt_sb->s_type);
 out2:
        path_release(&new_nd);
 out1:
@@ -1215,7 +1238,7 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
 {
        struct file_system_type * fstype;
        struct nameidata nd;
-       struct vfsmount *mnt;
+       struct vfsmount *mnt = NULL;
        struct super_block *sb;
        int retval = 0;
        unsigned long flags = 0;
@@ -1224,8 +1247,6 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
 
        if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
                return -EINVAL;
-       if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
-               return -EINVAL;
        if (dev_name && !memchr(dev_name, 0, PAGE_SIZE))
                return -EINVAL;
 
@@ -1239,6 +1260,11 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
        if ((new_flags & MS_MGC_MSK) == MS_MGC_VAL)
                flags = new_flags & ~MS_MGC_MSK;
 
+       /* For the rest we need the type */
+
+       if (!type_page || !memchr(type_page, 0, PAGE_SIZE))
+               return -EINVAL;
+
        /* loopback mount? This is special - requires fewer capabilities */
        if (strcmp(type_page, "bind")==0)
                return do_loopback(dev_name, dir_name);
@@ -1272,16 +1298,18 @@ long do_mount(char * dev_name, char * dir_name, char *type_page,
        if (IS_ERR(sb))
                goto dput_out;
 
-       retval = -ENOENT;
-       if (d_unhashed(nd.dentry) && !IS_ROOT(nd.dentry))
-               goto fail;
-
        /* Something was mounted here while we slept */
        while(d_mountpoint(nd.dentry) && follow_down(&nd.mnt, &nd.dentry))
                ;
-
-       retval = -ENOMEM;
-       mnt = add_vfsmnt(sb, nd.dentry, sb->s_root, nd.mnt, dev_name, dir_name);
+       retval = -ENOENT;
+       if (!nd.dentry->d_inode)
+               goto fail;
+       down(&nd.dentry->d_inode->i_zombie);
+       if (!IS_DEADDIR(nd.dentry->d_inode)) {
+               retval = -ENOMEM;
+               mnt = add_vfsmnt(&nd, sb->s_root, dev_name);
+       }
+       up(&nd.dentry->d_inode->i_zombie);
        if (!mnt)
                goto fail;
        retval = 0;
@@ -1312,15 +1340,6 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
        if (retval < 0)
                return retval;
 
-       /* copy_mount_options allows a NULL user pointer,
-        * and just returns zero in that case.  But if we
-        * allow the type to be NULL we will crash.
-        * Previously we did not check this case.
-        */
-       if (type_page == 0)
-               return -EINVAL;
-
-       lock_kernel();
        dir_page = getname(dir_name);
        retval = PTR_ERR(dir_page);
        if (IS_ERR(dir_page))
@@ -1331,8 +1350,10 @@ asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
                goto out2;
        retval = copy_mount_options (data, &data_page);
        if (retval >= 0) {
+               lock_kernel();
                retval = do_mount((char*)dev_page,dir_page,(char*)type_page,
                                      new_flags, (void*)data_page);
+               unlock_kernel();
                free_page(data_page);
        }
        free_page(dev_page);
@@ -1340,7 +1361,6 @@ out2:
        putname(dir_page);
 out1:
        free_page(type_page);
-       unlock_kernel();
        return retval;
 }
 
@@ -1490,12 +1510,11 @@ mount_it:
                                  path + 5 + path_start, 0,
                                  NULL, NULL);
                memcpy (path + path_start, "/dev/", 5);
-               vfsmnt = add_vfsmnt (sb, sb->s_root, sb->s_root, NULL,
-                                       path + path_start, "/");
+               vfsmnt = add_vfsmnt(NULL, sb->s_root, path + path_start);
        }
        else
-               vfsmnt = add_vfsmnt (sb, sb->s_root, sb->s_root, NULL,
-                                       "/dev/root", "/");
+               vfsmnt = add_vfsmnt(NULL, sb->s_root, "/dev/root");
+       /* FIXME: if something will try to umount us right now... */
        if (vfsmnt) {
                set_fs_root(current->fs, vfsmnt, sb->s_root);
                set_fs_pwd(current->fs, vfsmnt, sb->s_root);
@@ -1516,6 +1535,7 @@ static void chroot_fs_refs(struct dentry *old_root,
 
        read_lock(&tasklist_lock);
        for_each_task(p) {
+               /* FIXME - unprotected usage of ->fs + (harmless) race */
                if (!p->fs) continue;
                if (p->fs->root == old_root && p->fs->rootmnt == old_rootmnt)
                        set_fs_root(p->fs, new_rootmnt, new_root);
@@ -1576,7 +1596,10 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
        root_mnt = mntget(current->fs->rootmnt);
        root = dget(current->fs->root);
        down(&mount_sem);
+       down(&old_nd.dentry->d_inode->i_zombie);
        error = -ENOENT;
+       if (IS_DEADDIR(new_nd.dentry->d_inode))
+               goto out2;
        if (d_unhashed(new_nd.dentry) && !IS_ROOT(new_nd.dentry))
                goto out2;
        if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
@@ -1599,19 +1622,12 @@ asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
        } else if (!is_subdir(old_nd.dentry, new_nd.dentry))
                goto out2;
 
-       error = -ENOMEM;
-       name = __getname();
-       if (!name)
-               goto out2;
-
-       move_vfsmnt(new_nd.mnt, new_nd.dentry, NULL, NULL, "/");
-       move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL,
-                       __d_path(old_nd.dentry, old_nd.mnt, new_nd.dentry,
-                               new_nd.mnt, name, PAGE_SIZE));
-       putname(name);
+       move_vfsmnt(new_nd.mnt, new_nd.dentry, NULL, NULL);
+       move_vfsmnt(root_mnt, old_nd.dentry, old_nd.mnt, NULL);
        chroot_fs_refs(root,root_mnt,new_nd.dentry,new_nd.mnt);
        error = 0;
 out2:
+       up(&old_nd.dentry->d_inode->i_zombie);
        up(&mount_sem);
        dput(root);
        mntput(root_mnt);
@@ -1629,10 +1645,11 @@ out0:
 int __init change_root(kdev_t new_root_dev,const char *put_old)
 {
        kdev_t old_root_dev = ROOT_DEV;
-       struct vfsmount *old_rootmnt = mntget(current->fs->rootmnt);
+       struct vfsmount *old_rootmnt;
        struct nameidata devfs_nd, nd;
        int error = 0;
 
+       old_rootmnt = mntget(current->fs->rootmnt);
        /*  First unmount devfs if mounted  */
        if (path_init("/dev", LOOKUP_FOLLOW|LOOKUP_POSITIVE, &devfs_nd))
                error = path_walk("/dev", &devfs_nd);
@@ -1675,7 +1692,8 @@ int __init change_root(kdev_t new_root_dev,const char *put_old)
                printk(KERN_ERR "error %ld\n",blivet);
                return error;
        }
-       move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old", put_old);
+       /* FIXME: we should hold i_zombie on nd.dentry */
+       move_vfsmnt(old_rootmnt, nd.dentry, nd.mnt, "/dev/root.old");
        mntput(old_rootmnt);
        path_release(&nd);
        return 0;
index 45581895975f4f7521d49e674f3cf004a5b7152c..4f73a59ee3af5704098b8e4b58cabf2547b738c7 100644 (file)
@@ -496,7 +496,6 @@ static struct super_block *sysv_read_super(struct super_block *sb,
        sb->s_blocksize = sb->sv_block_size;
        sb->s_blocksize_bits = sb->sv_block_size_bits;
        /* set up enough so that it can read an inode */
-       sb->s_dev = dev;
        sb->s_op = &sysv_sops;
        root_inode = iget(sb,SYSV_ROOT_INO);
        sb->s_root = d_alloc_root(root_inode);
index 5f76abbb0a0a6d4d39356d06fc14e2414f683b6e..f3f575d7eba1d81a5439c710604f25156c875942 100644 (file)
@@ -1419,7 +1419,6 @@ udf_read_super(struct super_block *sb, void *options, int silent)
        return sb;
 
 error_out:
-       sb->s_dev = NODEV;
        if (UDF_SB_VAT(sb))
                iput(UDF_SB_VAT(sb));
        if (!(sb->s_flags & MS_RDONLY))
index a74290f55d725fde478da1fe1d2974f3bdd568be..86d1db58c506bf4eb1158255ef17793b44be3dd7 100644 (file)
@@ -51,10 +51,7 @@ struct pci_controler {
 #define PCIBIOS_MIN_IO         alpha_mv.min_io_address
 #define PCIBIOS_MIN_MEM                alpha_mv.min_mem_address
 
-extern inline void pcibios_set_master(struct pci_dev *dev)
-{
-       /* No special bus mastering setup handling */
-}
+extern void pcibios_set_master(struct pci_dev *dev);
 
 extern inline void pcibios_penalize_isa_irq(int irq)
 {
index 4c2f70170f48e5e97cdcf97ae5a08fd03bb600f7..6328750e1f358343fd44a1c9b13ccab1e6a9e544 100644 (file)
  * We leave one page for the initial stack page, and one page for
  * the initial process structure. Also, the console eats 3 MB for
  * the initial bootloader (one of which we can reclaim later).
- * With a few other pages for various reasons, we'll use an initial
- * load address of PAGE_OFFSET+0x310000UL
  */
 #define BOOT_PCB       0x20000000
 #define BOOT_ADDR      0x20000000
 /* Remove when official MILO sources have ELF support: */
 #define BOOT_SIZE      (16*1024)
 
-
+#ifdef CONFIG_ALPHA_LEGACY_START_ADDRESS
+#define KERNEL_START_PHYS      0x300000 /* Old bootloaders hardcoded this.  */
+#else
 #define KERNEL_START_PHYS      0x800000 /* Wildfire has a huge console */
+#endif
 
 #define KERNEL_START   (PAGE_OFFSET+KERNEL_START_PHYS)
 #define SWAPPER_PGD    KERNEL_START
index bccbe3f502ef7f6273d26eae43169734a24312df..39f91b60bc3c4e12870cda37285b35ced788ce1c 100644 (file)
@@ -20,7 +20,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -30,7 +30,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
@@ -44,7 +45,8 @@ static __inline__ void ide_init_default_hwifs(void)
 
         memset(&hw, 0, sizeof(hw));
 
-       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+       hw.irq = IRQ_HARDDISK;
        ide_register_hw(&hw, NULL);
 #endif
 }
index 590579747941287fc682ab2284878b43e45f0a04..53daa0969571af90e3d551e85b4c6f22dba49089 100644 (file)
@@ -13,7 +13,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -25,7 +25,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
index 1a09f182779ed4e3ab47f2d03a7e4a4f353a4527..dbdeb1fab06f347af0cccce4b8f1fedc59db0bd9 100644 (file)
@@ -13,7 +13,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -23,7 +23,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
index 0cfcf3aacb8de69313279877309855a1da92d14a..aff8aaf9cf989fbfbef0b0ad5e4ca9af378d4d84 100644 (file)
@@ -13,7 +13,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
 }
 
index cb1eac75a50396495e4044b9bc7a7e7ec4e2b22e..4a4d1b20cae2a913fe6e81d84a5f082618f42832 100644 (file)
@@ -13,7 +13,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -23,7 +23,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
index ccbc7cf76aa6f3f9895536595c328aad4f050634..827d81c2b7fc432dfab79f9bebdf71881f0f3509 100644 (file)
@@ -13,7 +13,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -25,7 +25,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
@@ -37,6 +38,7 @@ ide_init_default_hwifs(void)
 {
        hw_regs_t hw;
 
-       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+       hw.irq = IRQ_HARDDISK;
        ide_register_hw(&hw, NULL);
 }
index 3a1f00e3d0a2a085e9d76bc7fad5158e8fe359ee..3a9935c0b578e28df106afe772d321e7e81e2a5d 100644 (file)
@@ -17,7 +17,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg;
        int i;
@@ -37,7 +37,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += (1 << IO_SHIFT);
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) (ctrl_port << IO_SHIFT);
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
@@ -73,9 +74,11 @@ ide_init_default_hwifs(void)
        /* MAC 23/4/1999, swap these round so that the left hand
           hard disk is hda when viewed from the front. This
           doesn't match the silkscreen however. */
-       ide_init_hwif_ports(&hw,0x10,0x1e,EMPEG_IRQ_IDE2);
+       ide_init_hwif_ports(&hw,0x10,0x1e,NULL);
+       hw.irq = EMPEG_IRQ_IDE2;
        ide_register_hw(&hw, NULL);
-       ide_init_hwif_ports(&hw,0x00,0x0e,EMPEG_IRQ_IDE1);
+       ide_init_hwif_ports(&hw,0x00,0x0e,NULL);
+       hw.irq = EMPEG_IRQ_IDE1;
        ide_register_hw(&hw, NULL);
 
 #elif defined( CONFIG_SA1100_VICTOR )
@@ -87,7 +90,8 @@ ide_init_default_hwifs(void)
        /* set the pcmcia interface timing */
        MECR = 0x00060006;
 
-       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_GPIO7);
+       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+       hw.irq = IRQ_GPIO7;
        ide_register_hw(&hw, NULL);
 #else
 #error Missing IDE interface definition in include/asm/arch/ide.h
index 6f447f497badd800ffdd0d4e569f4cfdaf44e97c..2f1e63d82c67bb58e9ee1773892ba3ae9e0af26a 100644 (file)
@@ -15,6 +15,7 @@
  *   26-05-2000 JD     SA-1111 support added
  */
 #include <linux/config.h>
+#include <asm/irq.h>
 
 #define fixup_irq(x)   (x)
 
@@ -73,7 +74,7 @@ static int GPIO_11_27_spurious;               /* GPIOs that triggered when masked */
 static void sa1100_GPIO11_27_demux(int irq, void *dev_id, 
                                   struct pt_regs *regs)
 {
-       int i, irq, spurious;
+       int i, spurious;
 
        while( (irq = (GEDR & 0xfffff800)) ){
                /*
index 1fb25abd1e1089e1d6208b0c1f65297dd5627aca..fc38d57aaa97ce00bcb5e17b776b3ab837f644d6 100644 (file)
@@ -10,7 +10,7 @@
 #ifndef __ASM_ARCH_HARDWARE_H
 #define __ASM_ARCH_HARDWARE_H
 
-#ifndef __ASSEMBLER__
+#ifndef __ASSEMBLY__
 
 /*
  * Mapping areas
index a9e373e981e9b6f45a326d7895ce298281acda54..2ef90b55863f3e0569185ea1614879bbf7be3dfa 100644 (file)
@@ -15,7 +15,7 @@
  * This should follow whatever the default interface uses.
  */
 static __inline__ void
-ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int *irq)
 {
        ide_ioreg_t reg = (ide_ioreg_t) data_port;
        int i;
@@ -27,7 +27,8 @@ ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
                reg += 1;
        }
        hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
-       hw->irq = irq;
+       if (irq)
+               *irq = 0;
 }
 
 /*
@@ -39,7 +40,8 @@ ide_init_default_hwifs(void)
 {
        hw_regs_t hw;
 
-       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, 14);
+       ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, NULL);
+       hw.irq = 14;
        ide_register_hw(&hw, NULL);
 }
 
index d5dfe4f9125837082beaebf651d3d946e316568f..94fd1717069662db8fa820b9df9bb65f6839f552 100644 (file)
@@ -36,36 +36,36 @@ static __inline__ void atomic_add(int i, volatile atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        v->counter += i;
-       restore_flags (flags);
+       __restore_flags(flags);
 }
 
 static __inline__ void atomic_sub(int i, volatile atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        v->counter -= i;
-       restore_flags (flags);
+       __restore_flags(flags);
 }
 
 static __inline__ void atomic_inc(volatile atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        v->counter += 1;
-       restore_flags (flags);
+       __restore_flags(flags);
 }
 
 static __inline__ void atomic_dec(volatile atomic_t *v)
 {
        unsigned long flags;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        v->counter -= 1;
-       restore_flags (flags);
+       __restore_flags(flags);
 }
 
 static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
@@ -73,10 +73,10 @@ static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
        unsigned long flags;
        int result;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        v->counter -= 1;
        result = (v->counter == 0);
-       restore_flags (flags);
+       __restore_flags(flags);
 
        return result;
 }
@@ -86,10 +86,10 @@ extern __inline__ int atomic_add_negative(int i, volatile atomic_t *v)
        unsigned long flags;
        int result;
 
-       save_flags_cli(flags);
+       __save_flags_cli(flags);
        v->counter += i;
        result = (v->counter < 0);
-       restore_flags(flags);
+       __restore_flags(flags);
 
        return result;
 }
@@ -98,9 +98,9 @@ static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr
 {
        unsigned long flags;
 
-       save_flags_cli (flags);
+       __save_flags_cli(flags);
        *addr &= ~mask;
-       restore_flags (flags);
+       __restore_flags(flags);
 }
 
 #endif
index c09edf8b122d7e2d37ac27a52d9733d32fb762d2..50639037d8aeebcd2af19eb999656cbcd87d7d2e 100644 (file)
@@ -20,7 +20,6 @@ extern struct processor {
        void (*_set_pgd)(pgd_t *pgd);
        /* XCHG */
        unsigned long (*_xchg_1)(unsigned long x, volatile void *ptr);
-       unsigned long (*_xchg_2)(unsigned long x, volatile void *ptr);
        unsigned long (*_xchg_4)(unsigned long x, volatile void *ptr);
 } processor;
 
@@ -34,7 +33,6 @@ extern const struct processor arm3_processor_functions;
 #define cpu_do_idle()                          do { } while (0)
 #define cpu_switch_mm(pgd,tsk)                 processor._set_pgd(pgd)
 #define cpu_xchg_1(x,ptr)                      processor._xchg_1(x,ptr)
-#define cpu_xchg_2(x,ptr)                      processor._xchg_2(x,ptr)
 #define cpu_xchg_4(x,ptr)                      processor._xchg_4(x,ptr)
 
 extern void cpu_memc_update_all(pgd_t *pgd);
index b67e33a9d6ccfd523078d65deb1700c165edd5d0..67db9ab90c26447272045fd6f16173a88c7fe8cf 100644 (file)
@@ -6,7 +6,8 @@ typedef unsigned int dmach_t;
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/memory.h>
 #include <asm/arch/dma.h>
 
 /*
index 9d98486440b831fd5c189362a5348e09cc4c3e4e..05a94a2e63010e6bc5d7b3ef5622002ae634be2d 100644 (file)
@@ -1,7 +1,9 @@
 /*
  * linux/include/asm-arm/floppy.h
  *
- * (C) 1996 Russell King
+ * (C) 1996-2000 Russell King
+ *
+ * Note that we don't touch FLOPPY_DMA nor FLOPPY_IRQ here
  */
 #ifndef __ASM_ARM_FLOPPY_H
 #define __ASM_ARM_FLOPPY_H
 #define fd_disable_irq()       disable_irq(IRQ_FLOPPYDISK)
 #define fd_enable_irq()                enable_irq(IRQ_FLOPPYDISK)
 
-#define fd_request_dma()       request_dma(FLOPPY_DMA,"floppy")
-#define fd_free_dma()          free_dma(FLOPPY_DMA)
-#define fd_disable_dma()       disable_dma(FLOPPY_DMA)
-#define fd_enable_dma()                enable_dma(FLOPPY_DMA)
-#define fd_clear_dma_ff()      clear_dma_ff(FLOPPY_DMA)
-#define fd_set_dma_mode(mode)  set_dma_mode(FLOPPY_DMA, (mode))
-#define fd_set_dma_addr(addr)  set_dma_addr(FLOPPY_DMA, virt_to_bus((addr)))
-#define fd_set_dma_count(len)  set_dma_count(FLOPPY_DMA, (len))
+#define fd_request_dma()       request_dma(DMA_FLOPPY,"floppy")
+#define fd_free_dma()          free_dma(DMA_FLOPPY)
+#define fd_disable_dma()       disable_dma(DMA_FLOPPY)
+#define fd_enable_dma()                enable_dma(DMA_FLOPPY)
+#define fd_clear_dma_ff()      clear_dma_ff(DMA_FLOPPY)
+#define fd_set_dma_mode(mode)  set_dma_mode(DMA_FLOPPY, (mode))
+#define fd_set_dma_addr(addr)  set_dma_addr(DMA_FLOPPY, virt_to_bus((addr)))
+#define fd_set_dma_count(len)  set_dma_count(DMA_FLOPPY, (len))
 #define fd_cacheflush(addr,sz)
 
 /* need to clean up dma.h */
@@ -109,13 +111,12 @@ extern __inline__ void fd_scandrives (void)
 }
 
 #define FDC1 (0x3f0)
-static int FDC2 = -1;
 
 #define FLOPPY0_TYPE 4
 #define FLOPPY1_TYPE 4
 
 #define N_FDC 1
-#define N_DRIVE 8
+#define N_DRIVE 4
 
 #define FLOPPY_MOTOR_MASK 0xf0
 
index 871e50a6517f124f32db7c3760557d7e9331cc4b..fad9e7412b242e7635a3e8c236de6a4d1ab19b25 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/io.h
  *
- * Copyright (C) 1996-1999 Russell King
+ * Copyright (C) 1996-2000 Russell King
  *
  * Modifications:
  *  16-Sep-1996        RMK     Inlined the inx/outx functions & optimised for both
@@ -11,6 +11,7 @@
  *  27-Mar-1999        PJB     Second parameter of memcpy_toio is const..
  *  04-Apr-1999        PJB     Added check_signature.
  *  12-Dec-1999        RMK     More cleanups
+ *  18-Jun-2000 RMK    Removed virt_to_* and friends definitions
  */
 #ifndef __ASM_ARM_IO_H
 #define __ASM_ARM_IO_H
@@ -43,23 +44,7 @@ extern void insl(unsigned int port, void *from, int len);
 
 #ifdef __KERNEL__
 
-#include <asm/arch/memory.h>
-
-extern __inline__ unsigned long virt_to_phys(volatile void *x)
-{
-       return __virt_to_phys((unsigned long)(x));
-}
-
-extern __inline__ void *phys_to_virt(unsigned long x)
-{
-       return (void *)(__phys_to_virt((unsigned long)(x)));
-}
-
-/*
- * Virtual <-> DMA view memory address translations
- */
-#define virt_to_bus(x)         (__virt_to_bus((unsigned long)(x)))
-#define bus_to_virt(x)         ((void *)(__bus_to_virt((unsigned long)(x))))
+#include <asm/memory.h>
 
 /* the following macro is depreciated */
 #define ioaddr(port)                   __ioaddr((port))
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
new file mode 100644 (file)
index 0000000..837ea19
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * linux/include/asm-arm/memory.h
+ *
+ * Copyright (C) 2000 Russell King
+ *
+ * Note: this file should not be included by non-asm/.h files
+ *
+ * Modifications:
+ */
+#ifndef __ASM_ARM_MEMORY_H
+#define __ASM_ARM_MEMORY_H
+
+#include <asm/arch/memory.h>
+
+extern __inline__ unsigned long virt_to_phys(volatile void *x)
+{
+       return __virt_to_phys((unsigned long)(x));
+}
+
+extern __inline__ void *phys_to_virt(unsigned long x)
+{
+       return (void *)(__phys_to_virt((unsigned long)(x)));
+}
+
+/*
+ * Virtual <-> DMA view memory address translations
+ */
+#define virt_to_bus(x)         (__virt_to_bus((unsigned long)(x)))
+#define bus_to_virt(x)         ((void *)(__bus_to_virt((unsigned long)(x))))
+
+#endif
index bc113ae6e2b544312595260aab04140be1fbb6ed..36a3515e7a0db0fbbcd7659f2ff51b27fdfc3d66 100644 (file)
@@ -7,20 +7,16 @@
 #ifndef __ASM_PROC_SYSTEM_H
 #define __ASM_PROC_SYSTEM_H
 
-extern const char xchg_str[];
-
-#include <linux/config.h>
 #include <asm/proc-fns.h>
 
 extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
-       extern void arm_invalidptr(const char *, int);
+       extern void __bad_xchg(volatile void *, int);
 
        switch (size) {
                case 1: return cpu_xchg_1(x, ptr);
-               case 2: return cpu_xchg_2(x, ptr);
                case 4: return cpu_xchg_4(x, ptr);
-               default: arm_invalidptr(xchg_str, size);
+               default: __bad_xchg(ptr, size);
        }
        return 0;
 }
@@ -108,22 +104,4 @@ extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int
          : "memory");                                  \
        } while (0)
 
-/* For spinlocks etc */
-#define local_irq_save(x)      __save_flags_cli(x)
-#define local_irq_restore(x)   __restore_flags(x)
-#define local_irq_disable()    __cli()
-#define local_irq_enable()     __sti()
-
-#ifdef CONFIG_SMP
-#error SMP not supported
-#else
-
-#define cli() __cli()
-#define sti() __sti()
-#define save_flags(x)          __save_flags(x)
-#define restore_flags(x)       __restore_flags(x)
-#define save_flags_cli(x)      __save_flags_cli(x)
-
-#endif
-
 #endif
index 3b35be30912c7a7b33a21d51c7a8fce468e3d6e6..d9ef8ffd98d88037c799d291ffeafb4437bf59da 100644 (file)
@@ -7,20 +7,16 @@
 #ifndef __ASM_PROC_SYSTEM_H
 #define __ASM_PROC_SYSTEM_H
 
-#include <linux/config.h>
-
-extern const char xchg_str[];
-
 extern __inline__ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
-       extern void arm_invalidptr(const char *, int);
+       extern void __bad_xchg(volatile void *, int);
 
        switch (size) {
                case 1: __asm__ __volatile__ ("swpb %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
                        break;
                case 4: __asm__ __volatile__ ("swp %0, %1, [%2]" : "=r" (x) : "r" (x), "r" (ptr) : "memory");
                        break;
-               default: arm_invalidptr(xchg_str, size);
+               default: __bad_xchg(ptr, size);
        }
        return x;
 }
@@ -102,22 +98,4 @@ extern unsigned long cr_alignment;  /* defined in entry-armv.S */
        : "r" (x)                                               \
        : "memory")
 
-/* For spinlocks etc */
-#define local_irq_save(x)      __save_flags_cli(x)
-#define local_irq_restore(x)   __restore_flags(x)
-#define local_irq_disable()    __cli()
-#define local_irq_enable()     __sti()
-
-#ifdef CONFIG_SMP
-#error SMP not supported
-#else
-
-#define cli() __cli()
-#define sti() __sti()
-#define save_flags(x)          __save_flags(x)
-#define restore_flags(x)       __restore_flags(x)
-#define save_flags_cli(x)      __save_flags_cli(x)
-
-#endif
-
 #endif
index 961363cc71dcff3beef441e2b3b2ec5c3462e130..3126767a41670b0a2d557287590a7baa8f69c41b 100644 (file)
 
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
+
+#define predicate(x)   (x & 0xf0000000)
+#define PREDICATE_ALWAYS       0xe0000000
+
 #endif
 
 #endif /* __ASSEMBLY__ */
index b75a88411bf8397d3343ccc7a6dbe8624ccc2cd7..94073475d12784273a4069e664329b8ad282a64b 100644 (file)
@@ -381,7 +381,6 @@ extern unsigned int __machine_arch_type;
 
 #define tas(ptr) (xchg((ptr),1))
 
-extern void arm_malalignedptr(const char *, void *, volatile void *);
 extern asmlinkage void __backtrace(void);
 
 /*
@@ -411,4 +410,22 @@ extern struct task_struct *__switch_to(struct task_struct *prev, struct task_str
 
 #endif
 
+/* For spinlocks etc */
+#define local_irq_save(x)      __save_flags_cli(x)
+#define local_irq_restore(x)   __restore_flags(x)
+#define local_irq_disable()    __cli()
+#define local_irq_enable()     __sti()
+
+#ifdef CONFIG_SMP
+#error SMP not supported
+#else
+
+#define cli()                  __cli()
+#define sti()                  __sti()
+#define save_flags(x)          __save_flags(x)
+#define restore_flags(x)       __restore_flags(x)
+#define save_flags_cli(x)      __save_flags_cli(x)
+
+#endif
+
 #endif
index 8a1f8e9b69beb45722ca043e459fcf3b29cc02bb..3e7ace0916fea2cb29078b29bbc7a07cd225e21f 100644 (file)
@@ -47,7 +47,12 @@ struct poll_table_struct;
 #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS)
 
 /* And dynamically-tunable limits and defaults: */
-extern int max_files, nr_files, nr_free_files;
+struct files_stat_struct {
+       int nr_files;           /* read only */
+       int nr_free_files;      /* read only */
+       int max_files;          /* tunable */
+};
+extern struct files_stat_struct files_stat;
 extern int max_super_blocks, nr_super_blocks;
 
 #define NR_FILE  8192  /* this can well be larger on a larger system */
@@ -997,7 +1002,16 @@ extern int bmap(struct inode *, int);
 extern int notify_change(struct dentry *, struct iattr *);
 extern int permission(struct inode *, int);
 extern int get_write_access(struct inode *);
-extern void put_write_access(struct inode *);
+extern int deny_write_access(struct file *);
+static inline void put_write_access(struct inode * inode)
+{
+       atomic_dec(&inode->i_writecount);
+}
+static inline void allow_write_access(struct file *file)
+{
+       if (file)
+               atomic_inc(&file->f_dentry->d_inode->i_writecount);
+}
 extern int do_pipe(int *);
 
 extern int open_namei(const char *, int, int, struct nameidata *);
@@ -1037,7 +1051,7 @@ extern ino_t find_inode_number(struct dentry *, struct qstr *);
 /*
  * Type of the last component on LOOKUP_PARENT
  */
-enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT };
+enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 
 /*
  * "descriptor" for what we're up to with a read for sendfile().
@@ -1148,6 +1162,7 @@ extern struct inode_operations page_symlink_inode_operations;
 extern int vfs_readdir(struct file *, filldir_t, void *);
 extern int dcache_readdir(struct file *, void *, filldir_t);
 
+extern struct file_system_type *get_fs_type(const char *name);
 extern struct super_block *get_super(kdev_t);
 struct super_block *get_empty_super(void);
 extern void put_super(kdev_t);
@@ -1185,20 +1200,6 @@ extern void inode_setattr(struct inode *, struct iattr *);
  *
  */
 
-/*
- * We need to do a check-parent every time
- * after we have locked the parent - to verify
- * that the parent is still our parent and
- * that we are still hashed onto it..
- *
- * This is required in case two processes race
- * on removing (or moving) the same entry: the
- * parent lock will serialize them, but the
- * other process will be too late..
- */
-#define check_parent(dir, dentry) \
-       ((dir) == (dentry)->d_parent && !d_unhashed(dentry))
-
 /*
  * Locking the parent is needed to:
  *  - serialize directory operations
index 37cb9664e2d38f7593ccd14c583bf36c925c7097..e6325a2980d571162425cd8325cbe4c98577ea85 100644 (file)
@@ -185,6 +185,7 @@ typedef struct page {
 #define ClearPageUptodate(page)        clear_bit(PG_uptodate, &(page)->flags)
 #define PageDirty(page)                test_bit(PG_dirty, &(page)->flags)
 #define SetPageDirty(page)     set_bit(PG_dirty, &(page)->flags)
+#define ClearPageDirty(page)   clear_bit(PG_dirty, &(page)->flags)
 #define PageLocked(page)       test_bit(PG_locked, &(page)->flags)
 #define LockPage(page)         set_bit(PG_locked, &(page)->flags)
 #define TryLockPage(page)      test_and_set_bit(PG_locked, &(page)->flags)
index 61ab19b1fc5243e49f5bf3220b31335274e1ff83..adb571de252ebdb4c88a5d5d09477b3a55c1bac0 100644 (file)
@@ -26,7 +26,6 @@ struct vfsmount
        atomic_t mnt_count;
 
   char *mnt_devname;                   /* Name of device e.g. /dev/dsk/hda1 */
-  char *mnt_dirname;                   /* Name of directory mounted on */
        struct list_head mnt_list;
        uid_t mnt_owner;
 };
index 8e675705e77b905b5e5b916754c27adc13d6cf5d..ae2da13bed2338bc0f78cf3bd059a17e54dd9d51 100644 (file)
@@ -25,9 +25,11 @@ struct svc_cacherep {
        unsigned char           c_state,        /* unused, inprog, done */
                                c_type,         /* status, buffer */
                                c_secure : 1;   /* req came from port < 1024 */
-       struct in_addr          c_client;
+       struct sockaddr_in      c_addr;
        u32                     c_xid;
+       u32                     c_prot;
        u32                     c_proc;
+       u32                     c_vers;
        unsigned long           c_timestamp;
        union {
                struct svc_buf  u_buffer;
index 06a21296f965b7ddea6cca8533a7202143ae84d8..5fb55c73832344892eb8b5ed182ebf43f3a5594d 100644 (file)
@@ -95,18 +95,6 @@ int                  nfserrno(int errno);
 void                   exp_nlmdetach(void);
 
 
-extern __inline__ int
-exp_checkaddr(struct svc_client *clp, struct in_addr addr)
-{
-       struct in_addr  *ap = clp->cl_addr;
-       int             i;
-
-       for (i = clp->cl_naddr; i--; ap++)
-               if (ap->s_addr == addr.s_addr)
-                       return 1;
-       return 0;
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* NFSD_EXPORT_H */
index 42663e79b86b658a5869cc19548c916cff440314..26e8edd22666ac5690f7cb207c7f5083687e7140 100644 (file)
@@ -80,19 +80,19 @@ int         nfsd_racache_init(int);
 void           nfsd_racache_shutdown(void);
 int            nfsd_lookup(struct svc_rqst *, struct svc_fh *,
                                const char *, int, struct svc_fh *);
-#ifdef CONFIG_NFSD_V3
-int            nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *);
-#endif /* CONFIG_NFSD_V3 */
 int            nfsd_setattr(struct svc_rqst *, struct svc_fh *,
                                struct iattr *);
 int            nfsd_create(struct svc_rqst *, struct svc_fh *,
                                char *name, int len, struct iattr *attrs,
                                int type, dev_t rdev, struct svc_fh *res);
 #ifdef CONFIG_NFSD_V3
+int            nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *);
 int            nfsd_create_v3(struct svc_rqst *, struct svc_fh *,
                                char *name, int len, struct iattr *attrs,
                                struct svc_fh *res, int createmode,
                                u32 *verifier);
+int            nfsd_commit(struct svc_rqst *, struct svc_fh *,
+                               off_t, unsigned long);
 #endif /* CONFIG_NFSD_V3 */
 int            nfsd_open(struct svc_rqst *, struct svc_fh *, int,
                                int, struct file *);
@@ -122,10 +122,7 @@ int                nfsd_readdir(struct svc_rqst *, struct svc_fh *,
                                u32 *buffer, int *countp, u32 *verf);
 int            nfsd_statfs(struct svc_rqst *, struct svc_fh *,
                                struct statfs *);
-#ifdef CONFIG_NFSD_V3
-int            nfsd_commit(struct svc_rqst *, struct svc_fh *,
-                               off_t, unsigned long);
-#endif /* CONFIG_NFSD_V3 */
+
 int            nfsd_notify_change(struct inode *, struct iattr *);
 int            nfsd_permission(struct svc_export *, struct dentry *, int);
 
index 83320b810e4dd6fde8a1d10394ce2efdce40ab7b..39ab97f1496599576d243fe7d6485efe58d89642 100644 (file)
@@ -90,7 +90,7 @@ struct nfs_fhbase_new {
 };
 
 struct knfsd_fh {
-       int             fh_size;        /* significant for NFSv3.
+       unsigned int    fh_size;        /* significant for NFSv3.
                                         * Points to the current size while building
                                         * a new file handle
                                         */
@@ -149,14 +149,13 @@ typedef struct svc_fh {
        struct dentry *         fh_dentry;      /* validated dentry */
        struct svc_export *     fh_export;      /* export pointer */
        int                     fh_maxsize;     /* max size for fh_handle */
+
+       unsigned char           fh_locked;      /* inode locked by us */
+
 #ifdef CONFIG_NFSD_V3
        unsigned char           fh_post_saved;  /* post-op attrs saved */
        unsigned char           fh_pre_saved;   /* pre-op attrs saved */
-#endif /* CONFIG_NFSD_V3 */
-       unsigned char           fh_locked;      /* inode locked by us */
-       unsigned char           fh_dverified;   /* dentry has been checked */
 
-#ifdef CONFIG_NFSD_V3
        /* Pre-op attributes saved during fh_lock */
        __u64                   fh_pre_size;    /* size before operation */
        time_t                  fh_pre_mtime;   /* mtime before oper */
@@ -207,7 +206,7 @@ void        fh_put(struct svc_fh *);
 static __inline__ struct svc_fh *
 fh_copy(struct svc_fh *dst, struct svc_fh *src)
 {
-       if (src->fh_dverified || src->fh_locked) {
+       if (src->fh_dentry || src->fh_locked) {
                struct dentry *dentry = src->fh_dentry;
                printk(KERN_ERR "fh_copy: copying %s/%s, already verified!\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -241,7 +240,6 @@ fill_pre_wcc(struct svc_fh *fhp)
                        fhp->fh_pre_size  = inode->i_size;
                        fhp->fh_pre_saved = 1;
        }
-       fhp->fh_locked = 1;
 }
 
 /*
@@ -273,13 +271,18 @@ fill_post_wcc(struct svc_fh *fhp)
        fhp->fh_post_mtime      = inode->i_mtime;
        fhp->fh_post_ctime      = inode->i_ctime;
        fhp->fh_post_saved      = 1;
-       fhp->fh_locked    = 0;
 }
+#else
+#define        fill_pre_wcc(ignored)
+#define fill_post_wcc(notused)
 #endif /* CONFIG_NFSD_V3 */
 
 
 /*
  * Lock a file handle/inode
+ * NOTE: both fh_lock and fh_unlock are done "by hand" in
+ * vfs.c:nfsd_rename as it needs to grab 2 i_sem's at once
+ * so, any changes here should be reflected there.
  */
 static inline void
 fh_lock(struct svc_fh *fhp)
@@ -290,7 +293,7 @@ fh_lock(struct svc_fh *fhp)
        dfprintk(FILEOP, "nfsd: fh_lock(%s) locked = %d\n",
                        SVCFH_fmt(fhp), fhp->fh_locked);
 
-       if (!fhp->fh_dverified) {
+       if (!fhp->fh_dentry) {
                printk(KERN_ERR "fh_lock: fh not verified!\n");
                return;
        }
@@ -302,11 +305,8 @@ fh_lock(struct svc_fh *fhp)
 
        inode = dentry->d_inode;
        down(&inode->i_sem);
-#ifdef CONFIG_NFSD_V3
        fill_pre_wcc(fhp);
-#else
        fhp->fh_locked = 1;
-#endif /* CONFIG_NFSD_V3 */
 }
 
 /*
@@ -315,20 +315,13 @@ fh_lock(struct svc_fh *fhp)
 static inline void
 fh_unlock(struct svc_fh *fhp)
 {
-       if (!fhp->fh_dverified)
+       if (!fhp->fh_dentry)
                printk(KERN_ERR "fh_unlock: fh not verified!\n");
 
        if (fhp->fh_locked) {
-#ifdef CONFIG_NFSD_V3
                fill_post_wcc(fhp);
                up(&fhp->fh_dentry->d_inode->i_sem);
-#else
-               struct dentry *dentry = fhp->fh_dentry;
-               struct inode *inode = dentry->d_inode;
-
                fhp->fh_locked = 0;
-               up(&inode->i_sem);
-#endif /* CONFIG_NFSD_V3 */
        }
 }
 #endif /* __KERNEL__ */
index 61ac59d2a62b62e2f99870ecfd56520a1facd8d9..5ccee05aaffde49adbfd17d6d2bede744f22f002 100644 (file)
 #define PCI_DEVICE_ID_SI_6205          0x0205
 #define PCI_DEVICE_ID_SI_501           0x0406
 #define PCI_DEVICE_ID_SI_496           0x0496
-#define PCI_DEVICE_ID_SI_300        0x0300
+#define PCI_DEVICE_ID_SI_300           0x0300
 #define PCI_DEVICE_ID_SI_530           0x0530
-#define PCI_DEVICE_ID_SI_540        0x5300
+#define PCI_DEVICE_ID_SI_540           0x0540
 #define PCI_DEVICE_ID_SI_601           0x0601
 #define PCI_DEVICE_ID_SI_620           0x0620
-#define PCI_DEVICE_ID_SI_630        0x6300
+#define PCI_DEVICE_ID_SI_630           0x0630
 #define PCI_DEVICE_ID_SI_5107          0x5107
+#define PCI_DEVICE_ID_SI_5300          0x5300
 #define PCI_DEVICE_ID_SI_5511          0x5511
 #define PCI_DEVICE_ID_SI_5513          0x5513
 #define PCI_DEVICE_ID_SI_5571          0x5571
 #define PCI_DEVICE_ID_SI_5597          0x5597
 #define PCI_DEVICE_ID_SI_5598          0x5598
 #define PCI_DEVICE_ID_SI_5600          0x5600
+#define PCI_DEVICE_ID_SI_6300          0x6300
 #define PCI_DEVICE_ID_SI_6306          0x6306
 #define PCI_DEVICE_ID_SI_6326          0x6326
 #define PCI_DEVICE_ID_SI_7001          0x7001
index f3b8eefcc74fb4e595c8c194cf79886db9f8ebf4..f8c8f6b95524718f688fbdc62d7d23e67f820ec3 100644 (file)
@@ -128,19 +128,6 @@ struct ucred {
        __u32   gid;
 };
 
-/* Socket types. */
-
-#define SOCK_STREAM    1               /* stream (connection) socket   */
-#define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
-#define SOCK_RAW       3               /* raw socket                   */
-#define SOCK_RDM       4               /* reliably-delivered message   */
-#define SOCK_SEQPACKET 5               /* sequential packet socket     */
-#define SOCK_PACKET    10              /* linux specific way of        */
-                                       /* getting packets at the dev   */
-                                       /* level.  For writing rarp and */
-                                       /* other similar things on the  */
-                                       /* user level.                  */
-
 /* Supported address families. */
 #define AF_UNSPEC      0
 #define AF_UNIX                1       /* Unix domain sockets          */
index 568a89a469d9bf9d25a4bd83b59ca0ac47f64c23..bba1e159e27a7aafd9e24420ec0b19615df0a83a 100644 (file)
@@ -20,10 +20,11 @@ struct vm_struct {
 
 extern struct vm_struct * get_vm_area (unsigned long size, unsigned long flags);
 extern void vfree(void * addr);
-extern void * __vmalloc (unsigned long size, int gfp_mask);
+extern void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot);
 extern long vread(char *buf, char *addr, unsigned long count);
 extern void vmfree_area_pages(unsigned long address, unsigned long size);
-extern int vmalloc_area_pages(unsigned long address, unsigned long size , int gfp_mask);
+extern int vmalloc_area_pages(unsigned long address, unsigned long size,
+                              int gfp_mask, pgprot_t prot);
 
 extern struct vm_struct * vmlist;
 
@@ -34,7 +35,7 @@ extern struct vm_struct * vmlist;
  
 static inline void * vmalloc (unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM);
+       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
 }
 
 /*
@@ -43,7 +44,7 @@ static inline void * vmalloc (unsigned long size)
 
 static inline void * vmalloc_dma (unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL|GFP_DMA);
+       return __vmalloc(size, GFP_KERNEL|GFP_DMA, PAGE_KERNEL);
 }
 
 /*
@@ -52,7 +53,7 @@ static inline void * vmalloc_dma (unsigned long size)
  
 static inline void * vmalloc_32(unsigned long size)
 {
-       return __vmalloc(size, GFP_KERNEL);
+       return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL);
 }
 
 /*
index f1b638acfda1086736df5adce53434b80c3c5347..fac13b5421c07db33f92b86ce63f4673736a2b1b 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1490,7 +1490,7 @@ static int shm_swap_core(struct shmid_kernel *shp, unsigned long idx, swp_entry_
                return RETRY;
        if (shp->id != zero_id) swap_attempts++;
 
-       if (--counter < 0) /* failed */
+       if (--*counter < 0) /* failed */
                return FAILED;
        if (page_count(page_map) != 1)
                return RETRY;
index 3f3b5fc16fd89521b3436e3549f6decb7bdc1fe7..1daf64cc19b65a70096ca06ffedfdec617fa33c9 100644 (file)
@@ -104,32 +104,37 @@ int unregister_exec_domain(struct exec_domain *it)
 
 void __set_personality(unsigned long personality)
 {
-       struct exec_domain *it;
+       struct exec_domain *it, *prev;
 
        it = lookup_exec_domain(personality);
-       if (it) {
-               if (atomic_read(&current->fs->count) != 1) {
-                       struct fs_struct *new = copy_fs_struct(current->fs);
-                       struct fs_struct *old;
-                       if (!new) {
-                               put_exec_domain(it);
-                               return;
-                       }
-                       task_lock(current);
-                       old = current->fs;
-                       current->fs = new;
-                       task_unlock(current);
-                       put_fs_struct(old);
-               }
-               /*
-                * At that point we are guaranteed to be the sole owner of
-                * current->fs.
-                */
+       if (it == current->exec_domain) {
                current->personality = personality;
-               current->exec_domain = it;
-               set_fs_altroot();
-               put_exec_domain(current->exec_domain);
+               return;
+       }
+       if (!it)
+               return;
+       if (atomic_read(&current->fs->count) != 1) {
+               struct fs_struct *new = copy_fs_struct(current->fs);
+               struct fs_struct *old;
+               if (!new) {
+                       put_exec_domain(it);
+                       return;
+               }
+               task_lock(current);
+               old = current->fs;
+               current->fs = new;
+               task_unlock(current);
+               put_fs_struct(old);
        }
+       /*
+        * At that point we are guaranteed to be the sole owner of
+        * current->fs.
+        */
+       current->personality = personality;
+       prev = current->exec_domain;
+       current->exec_domain = it;
+       set_fs_altroot();
+       put_exec_domain(prev);
 }
 
 asmlinkage long sys_personality(unsigned long personality)
index 6a874a98264f256de0a2917e74934a96133c3bf9..dc8a747e17c1503a9f49878d481fb7ae0edf0417 100644 (file)
@@ -130,6 +130,7 @@ EXPORT_SYMBOL(highmem_start_page);
 /* filesystem internal functions */
 EXPORT_SYMBOL(def_blk_fops);
 EXPORT_SYMBOL(update_atime);
+EXPORT_SYMBOL(get_fs_type);
 EXPORT_SYMBOL(get_super);
 EXPORT_SYMBOL(get_empty_super);
 EXPORT_SYMBOL(getname);
@@ -500,7 +501,6 @@ EXPORT_SYMBOL(disk_name);   /* for md.c */
 
 /* binfmt_aout */
 EXPORT_SYMBOL(get_write_access);
-EXPORT_SYMBOL(put_write_access);
 
 /* dynamic registering of consoles */
 EXPORT_SYMBOL(register_console);
index c0c5c9053fa5ddcdea487ccc3f469d6e081fc397..5e5fbfe1b367652932fbf07452ac129d26787cda 100644 (file)
@@ -326,10 +326,11 @@ sys_init_module(const char *name_user, struct module *mod_user)
        /* Initialize the module.  */
        mod->flags |= MOD_INITIALIZING;
        atomic_set(&mod->uc.usecount,1);
-       if (mod->init && mod->init() != 0) {
+       if (mod->init && (error = mod->init()) != 0) {
                atomic_set(&mod->uc.usecount,0);
                mod->flags &= ~MOD_INITIALIZING;
-               error = -EBUSY;
+               if (error > 0)  /* Buggy module */
+                       error = -EBUSY;
                goto err0;
        }
        atomic_dec(&mod->uc.usecount);
index f85cc4213b8bcabc4c61e920c080f08401583996..fa30b064581f74f41cde88a444d8ba01ccb2b05e 100644 (file)
@@ -60,8 +60,8 @@ struct task_struct * init_tasks[NR_CPUS] = {&init_task, };
  * The run-queue lock locks the parts that actually access
  * and change the run-queues, and have to be interrupt-safe.
  */
-__cacheline_aligned spinlock_t runqueue_lock = SPIN_LOCK_UNLOCKED;  /* second */
-__cacheline_aligned rwlock_t tasklist_lock = RW_LOCK_UNLOCKED; /* third */
+spinlock_t runqueue_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;  /* second */
+rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED; /* third */
 
 static LIST_HEAD(runqueue_head);
 
index 5fc0418f966c0a91c3969d91400d2441723578ee..ab62787d1dfee1c6d3d07f8fbfe2b4bfb05b6d24 100644 (file)
@@ -255,9 +255,9 @@ static ctl_table fs_table[] = {
         0444, NULL, &proc_dointvec},
        {FS_STATINODE, "inode-state", &inodes_stat, 7*sizeof(int),
         0444, NULL, &proc_dointvec},
-       {FS_NRFILE, "file-nr", &nr_files, 3*sizeof(int),
+       {FS_NRFILE, "file-nr", &files_stat, 3*sizeof(int),
         0444, NULL, &proc_dointvec},
-       {FS_MAXFILE, "file-max", &max_files, sizeof(int),
+       {FS_MAXFILE, "file-max", &files_stat.max_files, sizeof(int),
         0644, NULL, &proc_dointvec},
        {FS_NRSUPER, "super-nr", &nr_super_blocks, sizeof(int),
         0444, NULL, &proc_dointvec},
index b1e2b8547fe69cb9c4a6efd92bd39d410b22f71a..360efacfbb9c1f750cd173096b16117bae74c97d 100644 (file)
@@ -195,6 +195,7 @@ repeat:
                         * to it causing all sorts of fun problems ...
                         */
                        remove_inode_page(page);
+                       ClearPageDirty(page);
 
                        UnlockPage(page);
                        page_cache_release(page);
@@ -500,7 +501,7 @@ void add_to_page_cache_locked(struct page * page, struct address_space *mapping,
 
 /*
  * This adds a page to the page cache, starting out as locked,
- * owned by us, referenced, but not uptodate and with no errors.
+ * owned by us, but unreferenced, not uptodate and with no errors.
  */
 static inline void __add_to_page_cache(struct page * page,
        struct address_space *mapping, unsigned long offset,
@@ -512,8 +513,8 @@ static inline void __add_to_page_cache(struct page * page,
        if (PageLocked(page))
                BUG();
 
-       flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty));
-       page->flags = flags | (1 << PG_locked) | (1 << PG_referenced);
+       flags = page->flags & ~((1 << PG_uptodate) | (1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced));
+       page->flags = flags | (1 << PG_locked);
        page_cache_get(page);
        page->index = offset;
        add_page_to_inode_queue(mapping, page);
index f5bb2599c8d4a8ed03e487d808dfca896d4ad543..3d331a31179b9b5981cbee6339e31e0e2e0bd697 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -166,6 +166,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
 {
        struct mm_struct * mm = current->mm;
        struct vm_area_struct * vma;
+       int correct_wcount = 0;
        int error;
 
        if (file && (!file->f_op || !file->f_op->mmap))
@@ -296,26 +297,15 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
                goto free_vma;
 
        if (file) {
-               int correct_wcount = 0;
                if (vma->vm_flags & VM_DENYWRITE) {
-                       if (atomic_read(&file->f_dentry->d_inode->i_writecount) > 0) {
-                               error = -ETXTBSY;
+                       error = deny_write_access(file);
+                       if (error)
                                goto free_vma;
-                       }
-                       /* f_op->mmap might possibly sleep
-                        * (generic_file_mmap doesn't, but other code
-                        * might). In any case, this takes care of any
-                        * race that this might cause.
-                        */
-                       atomic_dec(&file->f_dentry->d_inode->i_writecount);
                        correct_wcount = 1;
                }
                vma->vm_file = file;
                get_file(file);
                error = file->f_op->mmap(file, vma);
-               /* Fix up the count if necessary, then check for an error */
-               if (correct_wcount)
-                       atomic_inc(&file->f_dentry->d_inode->i_writecount);
                if (error)
                        goto unmap_and_free_vma;
        } else if (flags & MAP_SHARED) {
@@ -332,6 +322,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
        addr = vma->vm_start; /* can addr have changed?? */
        vmlist_modify_lock(mm);
        insert_vm_struct(mm, vma);
+       if (correct_wcount)
+               atomic_inc(&file->f_dentry->d_inode->i_writecount);
        merge_segments(mm, vma->vm_start, vma->vm_end);
        vmlist_modify_unlock(mm);
        
@@ -343,6 +335,8 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned lon
        return addr;
 
 unmap_and_free_vma:
+       if (correct_wcount)
+               atomic_inc(&file->f_dentry->d_inode->i_writecount);
        vma->vm_file = NULL;
        fput(file);
        /* Undo any partial mapping done by a device driver. */
@@ -694,9 +688,11 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
         * so release them, and unmap the page range..
         * If the one of the segments is only being partially unmapped,
         * it will put new vm_area_struct(s) into the address space.
+        * In that case we have to be careful with VM_DENYWRITE.
         */
        while ((mpnt = free) != NULL) {
                unsigned long st, end, size;
+               struct file *file = NULL;
 
                free = free->vm_next;
 
@@ -708,6 +704,11 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
                if (mpnt->vm_ops && mpnt->vm_ops->unmap)
                        mpnt->vm_ops->unmap(mpnt, st, size);
 
+               if (mpnt->vm_flags & VM_DENYWRITE &&
+                   (st != mpnt->vm_start || end != mpnt->vm_end) &&
+                   (file = mpnt->vm_file) != NULL) {
+                       atomic_dec(&file->f_dentry->d_inode->i_writecount);
+               }
                remove_shared_vm_struct(mpnt);
                mm->map_count--;
 
@@ -719,6 +720,8 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
                 * Fix the mapping, and free the old area if it wasn't reused.
                 */
                extra = unmap_fixup(mm, mpnt, st, size, extra);
+               if (file)
+                       atomic_inc(&file->f_dentry->d_inode->i_writecount);
        }
 
        /* Release the extra vma struct if it wasn't used */
index 926364499a505eae267beecacddb886b71359d92..18a60fdbde60aa8aee85fc98f13aefec6233ed51 100644 (file)
@@ -93,6 +93,8 @@ void __free_pages_ok (struct page *page, unsigned long order)
                BUG();
        if (PageDecrAfter(page))
                BUG();
+       if (PageDirty(page))
+               BUG();
 
        zone = page->zone;
 
index 2405aba2ffbfdc8d9c149a845a6f1e4bc1503e9b..72f3eaca49b326e9ce5ae9dfadf87c75aa613dc1 100644 (file)
@@ -58,8 +58,8 @@ void add_to_swap_cache(struct page *page, swp_entry_t entry)
                BUG();
        if (page->mapping)
                BUG();
-       flags = page->flags & ~((1 << PG_error) | (1 << PG_dirty));
-       page->flags = flags | (1 << PG_referenced) | (1 << PG_uptodate);
+       flags = page->flags & ~((1 << PG_error) | (1 << PG_dirty) | (1 << PG_referenced));
+       page->flags = flags | (1 << PG_uptodate);
        add_to_page_cache_locked(page, &swapper_space, entry.val);
 }
 
index 55ef476a38a077f24aa18a5f70dbbdebfc6c5bc7..5d3a7f23e80232122e8c509dcacc2f0e10b59101 100644 (file)
@@ -407,11 +407,11 @@ asmlinkage long sys_swapoff(const char * specialfile)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       lock_kernel();
        err = user_path_walk(specialfile, &nd);
        if (err)
                goto out;
 
+       lock_kernel();
        prev = -1;
        swap_list_lock();
        for (type = swap_list.head; type >= 0; type = swap_info[type].next) {
@@ -478,9 +478,9 @@ asmlinkage long sys_swapoff(const char * specialfile)
        err = 0;
 
 out_dput:
+       unlock_kernel();
        path_release(&nd);
 out:
-       unlock_kernel();
        return err;
 }
 
@@ -555,7 +555,6 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        unsigned long maxpages;
        int swapfilesize;
        struct block_device *bdev = NULL;
-       char *name;
        
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -586,14 +585,7 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags)
        } else {
                p->prio = --least_priority;
        }
-       name = getname(specialfile);
-       error = PTR_ERR(name);
-       if (IS_ERR(name))
-               goto bad_swap_2;
-       error = 0;
-       if (path_init(name, LOOKUP_FOLLOW|LOOKUP_POSITIVE, &nd))
-               error = path_walk(name, &nd);
-       putname(name);
+       error = user_path_walk(specialfile, &nd);
        if (error)
                goto bad_swap_2;
 
index b3f1cf5b76e012576c88811109a2dc69e5192969..57f3ca56cc7ec2d72fdc13fb8e6fc20b572fb1db 100644 (file)
@@ -91,7 +91,7 @@ void vmfree_area_pages(unsigned long address, unsigned long size)
 }
 
 static inline int alloc_area_pte (pte_t * pte, unsigned long address,
-                       unsigned long size, int gfp_mask)
+                       unsigned long size, int gfp_mask, pgprot_t prot)
 {
        unsigned long end;
 
@@ -106,14 +106,14 @@ static inline int alloc_area_pte (pte_t * pte, unsigned long address,
                page = alloc_page(gfp_mask);
                if (!page)
                        return -ENOMEM;
-               set_pte(pte, mk_pte(page, PAGE_KERNEL));
+               set_pte(pte, mk_pte(page, prot));
                address += PAGE_SIZE;
                pte++;
        } while (address < end);
        return 0;
 }
 
-static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask)
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask, pgprot_t prot)
 {
        unsigned long end;
 
@@ -125,7 +125,7 @@ static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
                pte_t * pte = pte_alloc_kernel(pmd, address);
                if (!pte)
                        return -ENOMEM;
-               if (alloc_area_pte(pte, address, end - address, gfp_mask))
+               if (alloc_area_pte(pte, address, end - address, gfp_mask, prot))
                        return -ENOMEM;
                address = (address + PMD_SIZE) & PMD_MASK;
                pmd++;
@@ -133,8 +133,8 @@ static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned lo
        return 0;
 }
 
-inline int vmalloc_area_pages (unsigned long address,
-                                       unsigned long size, int gfp_mask)
+inline int vmalloc_area_pages (unsigned long address, unsigned long size,
+                               int gfp_mask, pgprot_t prot)
 {
        pgd_t * dir;
        unsigned long end = address + size;
@@ -148,7 +148,7 @@ inline int vmalloc_area_pages (unsigned long address,
                pmd = pmd_alloc_kernel(dir, address);
                if (!pmd)
                        return -ENOMEM;
-               if (alloc_area_pmd(pmd, address, end - address, gfp_mask))
+               if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot))
                        return -ENOMEM;
                if (pgd_val(olddir) != pgd_val(*dir))
                        set_pgdir(address, *dir);
@@ -212,7 +212,7 @@ void vfree(void * addr)
        printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
 }
 
-void * __vmalloc (unsigned long size, int gfp_mask)
+void * __vmalloc (unsigned long size, int gfp_mask, pgprot_t prot)
 {
        void * addr;
        struct vm_struct *area;
@@ -228,7 +228,7 @@ void * __vmalloc (unsigned long size, int gfp_mask)
                return NULL;
        }
        addr = area->addr;
-       if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask)) {
+       if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask, prot)) {
                vfree(addr);
                BUG();
                return NULL;
index c209ff9910f287dd4df8e6a74fe9f96784b6bd8f..cd4a2bdb9247e4628a113d8af4f181bf77377511 100644 (file)
@@ -196,7 +196,7 @@ EXPORT_SYMBOL(__scm_send);
 
 /* Needed by unix.o */
 EXPORT_SYMBOL(scm_fp_dup);
-EXPORT_SYMBOL(max_files);
+EXPORT_SYMBOL(files_stat);
 EXPORT_SYMBOL(memcpy_toiovec);
 EXPORT_SYMBOL(csum_partial);
 
index e0a13d7259262588d83b73563ed8044e084a4b1f..f0f714ff0e84101b8d3666df6561ba4f057e2e26 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
+#include <net/checksum.h>
 #include <net/ip.h>
 #include <asm/uaccess.h>
 
@@ -371,6 +372,16 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
                dprintk("svc: recvfrom returned error %d\n", -err);
        }
 
+       if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
+               unsigned int csum = skb->csum;
+               csum = csum_partial(skb->h.raw, skb->len, csum);
+               if ((unsigned short)csum_fold(csum)) {
+                       skb_free_datagram(svsk->sk_sk, skb);
+                       svc_sock_received(svsk, 0);
+                       return 0;
+               }
+       }
+
        /* There may be more data */
        svsk->sk_data = 1;
 
index d71a527fe2f5884e5b9d19b4c2f8770c66717f27..20e0fc8c72bccc914e60b920663e55c77dcf7b7b 100644 (file)
@@ -445,7 +445,7 @@ static struct sock * unix_create1(struct socket *sock)
 {
        struct sock *sk;
 
-       if (atomic_read(&unix_nr_socks) >= 2*max_files)
+       if (atomic_read(&unix_nr_socks) >= 2*files_stat.max_files)
                return NULL;
 
        MOD_INC_USE_COUNT;