]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.1.131pre2 2.1.131pre2
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:29 +0000 (15:17 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:17:29 +0000 (15:17 -0500)
There's a pre-131-2 patch there on ftp.kernel.org in the testing
directory. This should have the NFS locking issues worked out (please
test), and also has a rather subtle but potentially very nasty deadlock
due to incorrect semaphore ordering with rmdir() hopefully fixed for good.
Alan, the regparm patches are also there.

                Linus

nfs: write back everything whenever some lock is changed (not just for
     unlock), and always invalidates the caches.

59 files changed:
CREDITS
Documentation/Configure.help
Makefile
arch/alpha/config.in
arch/alpha/kernel/bios32.c
arch/alpha/kernel/process.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/sys_dp264.c
arch/i386/boot/setup.S
arch/i386/config.in
arch/i386/kernel/apm.c
arch/i386/kernel/process.c
arch/i386/kernel/signal.c
arch/i386/kernel/vm86.c
arch/i386/mm/init.c
arch/i386/mm/ioremap.c
drivers/char/keyboard.c
drivers/char/lp.c
drivers/char/tty_io.c
drivers/scsi/ChangeLog.ncr53c8xx
drivers/scsi/README.ncr53c8xx
drivers/scsi/ncr53c8xx.c
drivers/scsi/ncr53c8xx.h
drivers/scsi/scsi_obsolete.c
drivers/sound/sb_common.c
drivers/video/atyfb.c
fs/affs/namei.c
fs/ext2/namei.c
fs/minix/namei.c
fs/namei.c
fs/nfs/file.c
fs/nfs/write.c
fs/nfsd/vfs.c
fs/open.c
fs/qnx4/namei.c
fs/sysv/namei.c
fs/ufs/namei.c
fs/umsdos/README-WIP.txt
fs/umsdos/check.c
fs/umsdos/dir.c
fs/umsdos/inode.c
fs/umsdos/namei.c
fs/umsdos/rdir.c
include/asm-i386/semaphore.h
include/linux/apm_bios.h
include/linux/linkage.h
include/linux/lp.h
include/linux/nfs_fs.h
include/linux/pci.h
include/linux/swap.h
include/linux/umsdos_fs.h
include/linux/umsdos_fs.p
init/main.c
kernel/fork.c
mm/filemap.c
mm/swap.c
mm/vmscan.c
net/ipv4/Config.in
net/ipv4/tcp_ipv4.c

diff --git a/CREDITS b/CREDITS
index ab7398163af79de5fbccca4b0cd7ffb17d51ef66..f17f3ef6ea6bf976f12bd8eacfb1f0c26c57bc78 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1116,11 +1116,11 @@ E: Kai.Makisara@metla.fi
 D: SCSI Tape Driver
 
 N: Hamish Macdonald
-E: hamish@border.ocunix.on.ca
+E: hamish_macdonald@westendsys.com
 D: Linux/68k port
-S: 102-B Valleystream Drive
-S: Nepean, Ontario
-S: Canada K2H-9E1
+S: 32 Clydesdale Avenue
+S: Kanata, Ontario
+S: Canada K2M-2G7
 
 N: Peter MacDonald
 D: SLS distribution
@@ -2074,7 +2074,7 @@ S: San Jose, California 95148
 S: USA
 
 N: Marc Zyngier
-E: maz@gloups.fdn.fr
+E: maz@wild-wind.fr.eu.org
 D: MD driver
 S: 11 rue Victor HUGO
 S: 95560 Montsoult
index d8176d3a44757c7941e38c919d90a38fbb3851f1..6fcb85efc9a4e8ee5dbe93c9d8ad89d615893f48 100644 (file)
@@ -2397,9 +2397,6 @@ CONFIG_IP_MASQUERADE
   information on the WWW at
   http://www.tor.shaw.wave.ca/~ambrose/kernel21.html. 
 
-  If you say Y here, you should also say Y to "IP: always defragment",
-  below. 
-
   If you say Y here, then the modules ip_masq_ftp.o (for ftp file
   transfers), ip_masq_irc.o (for irc chats), ip_masq_quake.o (you
   guessed it), ip_masq_vdolive.o (for VDOLive video connections),
@@ -2503,7 +2500,7 @@ CONFIG_IP_MASQUERADE_IPMARKFW
   The module will be called ip_masq_markfw.o. If you want to compile
   it as a module, say M here and read Documentation/modules.txt.
 
-IP: always defragment 
+IP: always defragment (required for masquerading)
 CONFIG_IP_ALWAYS_DEFRAG
   If you say Y here, then all incoming fragments (parts of IP packets
   that arose when some host between origin and destination decided
@@ -2511,18 +2508,13 @@ CONFIG_IP_ALWAYS_DEFRAG
   reassembled (defragmented) before being processed, even if they are
   about to be forwarded.
 
-  This option is highly recommended if you have said Y to "IP:
-  masquerading" because that facility requires that second and further
-  fragments can be related to TCP or UDP port numbers, which are only
-  stored in the first fragment.
+  You must say Y here if you want to enable "IP: masquerading" or "IP:
+  transparent proxying".
 
   When using "IP: firewalling" support, you might also want to say Y
   here, to have a more reliable firewall (otherwise second and further
   fragments must be dealt with by the firewall, which can be tricky).
 
-  When using "IP: transparent proxying", this option is implicit,
-  although it is safe to say Y here.
-
   Only say Y here if running either a firewall that is the sole link
   to your network or a transparent proxy; never ever say Y here for a
   normal router or host.
@@ -3868,7 +3860,7 @@ CONFIG_SCSI_NCR53C7xx_DISCONNECT
 
 NCR53C8XX SCSI support
 CONFIG_SCSI_NCR53C8XX
-  This is the BSD ncr driver adapted to linux for the NCR53C8XX family
+  This is the BSD ncr driver adapted to Linux for the NCR53C8XX family
   of PCI-SCSI controllers. This driver supports parity checking,
   tagged command queuing and fast synchronous data transfers up to 80
   MB/s with wide FAST-40 LVD devices and controllers.
@@ -8328,6 +8320,16 @@ CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
   ignored. Without this the Thinkpad 560 has troubles with the user
   level daemon apmd, and with the PCMCIA package pcmcia-cs.
 
+Ignore multiple suspend/resume cycles
+CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+  This option is necessary on the Dell Inspiron 3200, but should be
+  safe for all other laptops. When enabled, a system suspend event
+  that occurs within one second of a resume is ignored. Without this
+  the Inspiron will shut itself off a few seconds after you open the
+  lid, requiring you to press the power button to resume it a second
+  time.
+  Say Y.
+
 Watchdog Timer Support 
 CONFIG_WATCHDOG
   If you say Y here (and to one of the following options) and create a
index c3b95e1f1df7b5829d9d5f810f978a9ba05ff795..78dea7f6319c4d4282a03aa5cf977f7b59cef523 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 130
+SUBLEVEL = 131
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
index 8b17580b541efacb249a5f2695df36793d2b2e12..48e924fd79683db0543938f5b2fce41d7b038cd6 100644 (file)
@@ -22,14 +22,6 @@ endmenu
 mainmenu_option next_comment
 comment 'General setup'
 
-unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
-
-if [ "`uname`" != "Linux" ]; then
-  define_bool CONFIG_CROSSCOMPILE y
-else
-  define_bool CONFIG_NATIVE y
-fi
-
 choice 'Alpha system type' \
        "Generic                CONFIG_ALPHA_GENERIC            \
         Alcor/Alpha-XLT        CONFIG_ALPHA_ALCOR              \
index 8f25f7020c82c4458ec44a05d526278f388fe9f4..1c7823397b7ff6b70a08b79c907e80c0b6689600 100644 (file)
@@ -296,60 +296,82 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
  * on SRM.  It is more trouble than it iw worth to conditionalize this.
  */
 
-static struct {
-       struct reset_irq {
-               struct pci_dev *dev;
-               u8 irq;
-       } irq[16];
-       int irq_count;
-
-       struct reset_io {
-               struct pci_dev *dev;
-               u8 reg;
-               u32 io;
-       } io[16];
-       int io_count;
-} srm_resets;
+struct srm_irq_reset {
+       struct srm_irq_reset *next;
+       struct pci_dev *dev;
+       u8 irq;
+} *srm_irq_resets;
+
+struct srm_io_reset {
+       struct srm_io_reset *next;
+       struct pci_dev *dev;
+       u32 io;
+       u8 reg;
+} *srm_io_resets;
 
 /* Apply the collected reset modifications.  */
 
 void
 reset_for_srm(void)
 {
-       struct pci_dev *dev;
-       int i;
+       struct srm_irq_reset *qreset;
+       struct srm_io_reset *ireset;
 
        /* Reset any IRQs that we changed.  */
-       for (i = 0; i < srm_resets.irq_count; i++) {
-               dev = srm_resets.irq[i].dev;
-
-               pcibios_write_config_byte(dev->bus->number, dev->devfn,
+       for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
+               pcibios_write_config_byte(qreset->dev->bus->number,
+                                         qreset->dev->devfn,
                                          PCI_INTERRUPT_LINE,
-                                         srm_resets.irq[i].irq);
+                                         qreset->irq);
 #if 1
                printk("reset_for_srm: bus %d slot 0x%x "
                       "SRM IRQ 0x%x changed back from 0x%x\n",
-                      dev->bus->number, PCI_SLOT(dev->devfn),
-                      srm_resets.irq[i].irq, dev->irq);
+                      qreset->dev->bus->number,
+                      PCI_SLOT(qreset->dev->devfn),
+                      qreset->irq, qreset->dev->irq);
 #endif
        }
 
        /* Reset any IO addresses that we changed.  */
-       for (i = 0; i < srm_resets.io_count; i++) {
-               dev = srm_resets.io[i].dev;
-
-               pcibios_write_config_byte(dev->bus->number, dev->devfn,
-                                         srm_resets.io[i].reg,
-                                         srm_resets.io[i].io);
+       for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+               pcibios_write_config_dword(ireset->dev->bus->number,
+                                          ireset->dev->devfn,
+                                          ireset->reg, ireset->io);
 #if 1
                printk("reset_for_srm: bus %d slot 0x%x "
-                      "SRM IO restored to 0x%x\n",
-                      dev->bus->number, PCI_SLOT(dev->devfn),
-                      srm_resets.io[i].io);
+                      "SRM MEM/IO restored to 0x%x\n",
+                      ireset->dev->bus->number,
+                      PCI_SLOT(ireset->dev->devfn),
+                      ireset->io);
 #endif
        }
 }
 
+static void
+new_irq_reset(struct pci_dev *dev, u8 irq)
+{
+       struct srm_irq_reset *n;
+       n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+       n->next = srm_irq_resets;
+       n->dev = dev;
+       n->irq = irq;
+       srm_irq_resets = n;
+}
+
+static void
+new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
+{
+       struct srm_io_reset *n;
+       n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+       n->next = srm_io_resets;
+       n->dev = dev;
+       n->reg = reg;
+       n->io = io;
+       srm_io_resets = n;
+}
+
 
 /*
  * Disable PCI device DEV so that it does not respond to I/O or memory
@@ -426,6 +448,7 @@ layout_dev(struct pci_dev *dev)
        struct pci_bus *bus;
        unsigned short cmd;
        unsigned int base, mask, size, off, idx;
+       unsigned int orig_base;
        unsigned int alignto;
        unsigned long handle;
 
@@ -467,6 +490,8 @@ layout_dev(struct pci_dev *dev)
                 * Figure out how much space and of what type this
                 * device wants.
                 */
+               pcibios_read_config_dword(bus->number, dev->devfn, off,
+                                         &orig_base);
                pcibios_write_config_dword(bus->number, dev->devfn, off,
                                           0xffffffff);
                pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
@@ -504,8 +529,10 @@ layout_dev(struct pci_dev *dev)
                        alignto = MAX(0x800, size);
                        base = ALIGN(io_base, alignto);
                        io_base = base + size;
+
                        pcibios_write_config_dword(bus->number, dev->devfn, 
                                                   off, base | 0x1);
+                       new_io_reset(dev, off, orig_base);
 
                        handle = PCI_HANDLE(bus->number) | base | 1;
                        dev->base_address[idx] = handle;
@@ -582,8 +609,11 @@ layout_dev(struct pci_dev *dev)
                                }
                        }
                        mem_base = base + size;
+
                        pcibios_write_config_dword(bus->number, dev->devfn,
                                                   off, base);
+                       new_io_reset(dev, off, orig_base);
+
                        handle = PCI_HANDLE(bus->number) | base;
                        dev->base_address[idx] = handle;
 
@@ -596,9 +626,16 @@ layout_dev(struct pci_dev *dev)
                         * addresses to be used.
                         */
                        if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-                               pcibios_write_config_dword(bus->number,
-                                                          dev->devfn,
-                                                          off+4, 0);
+                               unsigned int orig_base2;
+                               pcibios_read_config_dword(bus->number,
+                                                         dev->devfn,
+                                                         off+4, &orig_base2);
+                               if (0 != orig_base2) {
+                                       pcibios_write_config_dword(bus->number,
+                                                                  dev->devfn,
+                                                                  off+4, 0);
+                                       new_io_reset (dev, off+4, orig_base2);
+                               }
                                /* Bypass hi reg in the loop.  */
                                dev->base_address[++idx] = 0;
 
@@ -720,10 +757,9 @@ layout_bus(struct pci_bus *bus)
                                           PCI_IO_BASE, l);
 
                /*
-                * Also:
-                *       clear out the upper 16 bits of IO base/limit.
-                *       clear out the upper 32 bits of PREF base/limit.
-               */
+                * Clear out the upper 16 bits of IO base/limit.
+                * Clear out the upper 32 bits of PREF base/limit.
+                */
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
                                           PCI_IO_BASE_UPPER16, 0);
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
@@ -738,6 +774,7 @@ layout_bus(struct pci_bus *bus)
                l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
                pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
                                           PCI_MEMORY_BASE, l);
+
                /*
                 * Turn off downstream PF memory address range, unless
                 * there is a VGA behind this bridge, in which case, we
@@ -839,7 +876,6 @@ check_behind_io(struct pci_dev *dev)
 {
        struct pci_bus *bus = dev->bus;
        unsigned int reg, orig_base, new_base, found_one = 0;
-       struct reset_io *ior;
 
        for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
                /* Read the current setting, check for I/O space and >= 64K */
@@ -870,10 +906,7 @@ printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n",
                pcibios_write_config_dword(bus->number, dev->devfn,
                                           reg, new_base);
 
-               ior = &srm_resets.io[srm_resets.io_count++];
-               ior->dev = dev;
-               ior->reg = reg;
-               ior->io = orig_base;
+               new_io_reset(dev, reg, orig_base);
                found_one++;
        }
 
@@ -990,8 +1023,6 @@ common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
                                                 &irq_orig);
 
                        if (irq_orig != dev->irq) {
-                               struct reset_irq *r;
-
                                DBG_DEVS(("common_pci_fixup: bus %d "
                                          "slot 0x%x SRM IRQ 0x%x "
                                          "changed to 0x%x\n",
@@ -999,9 +1030,7 @@ common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
                                          PCI_SLOT(dev->devfn),
                                          irq_orig, dev->irq));
 
-                               r = &srm_resets.irq[srm_resets.irq_count++];
-                               r->dev = dev;
-                               r->irq = irq_orig;
+                               new_irq_reset(dev, irq_orig);
                        }
                }
 
index 0f6c843bc058fd0b7c2c7e23dd0d12fb104c0f00..562778366da8586fb7530a4acff5acc75e7f3cf3 100644 (file)
@@ -133,18 +133,15 @@ generic_kill_arch (int mode, char *restart_cmd)
                                strncpy((char *)cpup->ipc_buffer, restart_cmd,
                                        sizeof(cpup->ipc_buffer));
                        }
-               }
-               else {
+               } else {
                        flags |=  0x00040000UL; /* "remain halted" */
                }
                        
                cpup->flags = flags;                                           
                mb();                                           
 
-               if (alpha_use_srm_setup) {
-                       reset_for_srm();
-                       set_hae(srm_hae);
-               }
+               reset_for_srm();
+               set_hae(srm_hae);
 
 #ifdef CONFIG_DUMMY_CONSOLE
                /* This has the effect of reseting the VGA video origin.  */
@@ -156,10 +153,8 @@ generic_kill_arch (int mode, char *restart_cmd)
        /* Reset rtc to defaults.  */
        {
                unsigned char control;
-               unsigned long flags;
 
-               /* I'm not sure if i really need to disable interrupts here. */
-               save_and_cli(flags);
+               cli();
 
                /* Reset periodic interrupt frequency.  */
                CMOS_WRITE(0x26, RTC_FREQ_SELECT);
@@ -170,7 +165,7 @@ generic_kill_arch (int mode, char *restart_cmd)
                CMOS_WRITE(control, RTC_CONTROL);       
                CMOS_READ(RTC_INTR_FLAGS);
 
-               restore_flags(flags);
+               sti();
        }
 #endif
 
index a94bd6bcaec5da70dd45c88fa8537a893849f391..f357830e34e011759522b9b44553043e9e576e48 100644 (file)
 
 #include "proto.h"
 
-#if 1
-# define DBG_SRM(args)         printk args
-#else
-# define DBG_SRM(args)
-#endif
-
 struct hwrpb_struct *hwrpb;
 unsigned long srm_hae;
 
@@ -114,6 +108,7 @@ extern struct alpha_machine_vector lx164_mv;
 extern struct alpha_machine_vector miata_mv;
 extern struct alpha_machine_vector mikasa_mv;
 extern struct alpha_machine_vector mikasa_primo_mv;
+extern struct alpha_machine_vector monet_mv;
 extern struct alpha_machine_vector noname_mv;
 extern struct alpha_machine_vector noritake_mv;
 extern struct alpha_machine_vector noritake_primo_mv;
@@ -127,6 +122,34 @@ extern struct alpha_machine_vector sx164_mv;
 extern struct alpha_machine_vector takara_mv;
 extern struct alpha_machine_vector xl_mv;
 extern struct alpha_machine_vector xlt_mv;
+#pragma weak alcor_mv
+#pragma weak alphabook1_mv
+#pragma weak avanti_mv
+#pragma weak cabriolet_mv
+#pragma weak dp264_mv
+#pragma weak eb164_mv
+#pragma weak eb64p_mv
+#pragma weak eb66_mv
+#pragma weak eb66p_mv
+#pragma weak jensen_mv
+#pragma weak lx164_mv
+#pragma weak miata_mv
+#pragma weak mikasa_mv
+#pragma weak mikasa_primo_mv
+#pragma weak monet_mv
+#pragma weak noname_mv
+#pragma weak noritake_mv
+#pragma weak noritake_primo_mv
+#pragma weak p2k_mv
+#pragma weak pc164_mv
+#pragma weak rawhide_mv
+#pragma weak ruffian_mv
+#pragma weak sable_mv
+#pragma weak sable_gamma_mv
+#pragma weak sx164_mv
+#pragma weak takara_mv
+#pragma weak xl_mv
+#pragma weak xlt_mv
 
 
 void __init
@@ -197,26 +220,18 @@ setup_arch(char **cmdline_p, unsigned long * memory_start_p,
                                 cpu->type);
        }
 
-#ifdef CONFIG_ALPHA_GENERIC
        if (!vec) {
                panic("Unsupported system type: %s%s%s (%ld %ld)\n",
                      type_name, (*var_name ? " variation " : ""), var_name,
                      hwrpb->sys_type, hwrpb->sys_variation);
        }
-       alpha_mv = *vec;
+       if (vec != &alpha_mv)
+               alpha_mv = *vec;
 
+#ifdef CONFIG_ALPHA_GENERIC
        /* Assume that we've booted from SRM if we havn't booted from MILO.
           Detect the later by looking for "MILO" in the system serial nr.  */
        alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#else
-       /* Once we're sure we can reliably identify systems, we should
-          simply panic as we do above.  */
-       if (vec != &alpha_mv) {
-               printk("WARNING: Not configured for system type: %s%s%s "
-                      "(%ld %ld)\nContinuing with trepidation...\n",
-                      type_name, (*var_name ? " variation " : ""), var_name,
-                      hwrpb->sys_type, hwrpb->sys_variation);
-       }
 #endif
 
        printk("Booting on %s%s%s using machine vector %s\n",
@@ -361,7 +376,6 @@ static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8};
 static struct alpha_machine_vector * __init
 get_sysvec(long type, long variation, long cpu)
 {
-#ifdef CONFIG_ALPHA_GENERIC
        static struct alpha_machine_vector *systype_vecs[] __initlocaldata =
        {
                NULL,           /* 0 */
@@ -398,7 +412,7 @@ get_sysvec(long type, long variation, long cpu)
                NULL,           /* XXM */
                &takara_mv,
                NULL,           /* Yukon */
-               &dp264_mv,
+               NULL,           /* Tsunami -- see variation.  */
                NULL,           /* Wildfire */
                NULL,           /* CUSCO */
        };
@@ -432,6 +446,19 @@ get_sysvec(long type, long variation, long cpu)
                &eb66p_mv
        };
 
+       static struct alpha_machine_vector *tsunami_vecs[]  __initlocaldata =
+       {
+               NULL,
+               &dp264_mv,              /* dp164 */
+               &dp264_mv,              /* warhol */
+               &dp264_mv,              /* windjammer */
+               &monet_mv,              /* monet */
+               &dp264_mv,              /* clipper */
+               &dp264_mv,              /* goldrush */
+               &dp264_mv,              /* webbrick */
+               &dp264_mv,              /* catamaran */
+       };
+
        /* ??? Do we need to distinguish between Rawhides?  */
 
        struct alpha_machine_vector *vec;
@@ -472,6 +499,10 @@ get_sysvec(long type, long variation, long cpu)
                        if (member < N(eb66_indices))
                                vec = eb66_vecs[eb66_indices[member]];
                        break;
+               case ST_DEC_TSUNAMI:
+                       if (member < N(tsunami_indices))
+                               vec = tsunami_vecs[tsunami_indices[member]];
+                       break;
                case ST_DEC_1000:
                        cpu &= 0xffffffff;
                        if (cpu == EV5_CPU || cpu == EV56_CPU)
@@ -496,17 +527,11 @@ get_sysvec(long type, long variation, long cpu)
                }
        }
        return vec;
-#else
-       /* TODO: verify that the system is of the type for which we
-          were configured.  For now, cop out and return success.  */
-       return &alpha_mv;
-#endif /* GENERIC */
 }
 
 static struct alpha_machine_vector * __init
 get_sysvec_byname(const char *name)
 {
-#ifdef CONFIG_ALPHA_GENERIC
        static struct alpha_machine_vector *all_vecs[] __initlocaldata =
        {
                &alcor_mv,
@@ -523,6 +548,7 @@ get_sysvec_byname(const char *name)
                &miata_mv,
                &mikasa_mv,
                &mikasa_primo_mv,
+               &monet_mv,
                &noname_mv,
                &noritake_mv,
                &noritake_primo_mv,
@@ -545,11 +571,6 @@ get_sysvec_byname(const char *name)
                        return mv;
        }
        return NULL;
-#else
-       if (strcasecmp(alpha_mv.vector_name, name) == 0)
-               return &alpha_mv;
-       return NULL;
-#endif
 }
 
 static void
index a398c24c9359f5bd0de4556d1f980dde40605540..9ac7abb3648e0f1e2775997ebf799af75be7800d 100644 (file)
 #include "bios32.h"
 #include "machvec.h"
 
-struct hwrpb_struct *hwrpb;
-
-/* hwrpb->sys_variation helpers */
-#define MEMBER_ID(x) (((x)>>10)&0x3f)
-
-#define DP264_ID       1
-#define MONET_ID       4
-#define GOLDRUSH_ID    6
-#define WEBBRICK_ID    7
-
 #define dev2hose(d) (bus2hose[(d)->bus->number]->pci_hose_index)
 
 /*
@@ -301,28 +291,22 @@ static void __init
 dp264_pci_fixup(void)
 {
        layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+       common_pci_fixup(dp264_map_irq, common_swizzle);
+       SMC669_Init();
+}
 
-       /* must do map and/or swizzle different on some */
-       switch (MEMBER_ID(hwrpb->sys_variation)) {
-       case MONET_ID:
-           common_pci_fixup(monet_map_irq, monet_swizzle);
-           /* es1888_init(); */ /* later? */
-           break;
-
-       case DP264_ID:
-       case GOLDRUSH_ID:
-       case WEBBRICK_ID:
-       default:
-           common_pci_fixup(dp264_map_irq, common_swizzle);
-           break;
-       } /* end MEMBER_ID switch */
-
+static void __init
+monet_pci_fixup(void)
+{
+       layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+       common_pci_fixup(monet_map_irq, monet_swizzle);
+       /* es1888_init(); */ /* later? */
        SMC669_Init();
 }
 
 
 /*
- * The System Vector
+ * The System Vectors
  */
 
 struct alpha_machine_vector dp264_mv __initmv = {
@@ -347,3 +331,27 @@ struct alpha_machine_vector dp264_mv __initmv = {
        kill_arch:              generic_kill_arch,
 };
 ALIAS_MV(dp264)
+
+struct alpha_machine_vector monet_mv __initmv = {
+       vector_name:            "Monet",
+       DO_EV6_MMU,
+       DO_DEFAULT_RTC,
+       DO_TSUNAMI_IO,
+       DO_TSUNAMI_BUS,
+       machine_check:          tsunami_machine_check,
+       max_dma_address:        ALPHA_MAX_DMA_ADDRESS,
+
+       nr_irqs:                64,
+       irq_probe_mask:         _PROBE_MASK(64),
+       update_irq_hw:          dp264_update_irq_hw,
+       ack_irq:                generic_ack_irq,
+       device_interrupt:       dp264_device_interrupt,
+
+       init_arch:              tsunami_init_arch,
+       init_irq:               dp264_init_irq,
+       init_pit:               generic_init_pit,
+       pci_fixup:              monet_pci_fixup,
+       kill_arch:              generic_kill_arch,
+};
+/* No alpha_mv alias for monet, since we compile it in unconditionally
+   with DP264; setup_arch knows how to cope.  */
index a5805750d9924833ef98a225cfa606f81f82bfb7..a2c8ecb37b93ef4a81421d327a7e8c79c9fd79af 100644 (file)
@@ -396,8 +396,6 @@ no_psmouse:
        cmp     bx,#0x0504d     ! check for "PM" signature
        jne     done_apm_bios   ! no signature -> no APM BIOS
 
-       mov     [64],ax         ! record the APM BIOS version
-       mov     [76],cx         !       and flags
        and     cx,#0x02        ! Is 32 bit supported?
        je      done_apm_bios   !       no ...
 
@@ -416,6 +414,26 @@ no_psmouse:
        mov     [74],dx         ! BIOS data segment
        mov     [78],esi        ! BIOS code segment length
        mov     [82],di         ! BIOS data segment length
+!
+! Redo the installation check as the 32 bit connect
+! modifies the flags returned on some BIOSs
+!
+       mov     ax,#0x05300     ! APM BIOS installation check
+       xor     bx,bx
+       int     0x15
+       jc      apm_disconnect  ! error -> should not happen, tidy up
+
+       cmp     bx,#0x0504d     ! check for "PM" signature
+       jne     apm_disconnect  ! no signature -> should not happen, tidy up
+
+       mov     [64],ax         ! record the APM BIOS version
+       mov     [76],cx         !       and flags
+       jmp     done_apm_bios
+
+apm_disconnect:
+       mov     ax,#0x05304     ! Disconnect
+       xor     bx,bx
+       int     0x15            ! ignore return code
        jmp     done_apm_bios
 
 no_32_apm_bios:
index 54448e7a3068ce732782cfafda19ba94316d176c..a22692bcab5ee5a819864e82479c3b912b518096 100644 (file)
@@ -72,6 +72,7 @@ if [ "$CONFIG_APM" = "y" ]; then
   bool '   Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
   bool '   Power off on shutdown' CONFIG_APM_POWER_OFF
   bool '   Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+  bool '   Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 fi
 
 endmenu
index 88670e68d6cca7baf679c2028a9b44bd47561917..1cbc824f51d43a56988e15ea0ca9fa3210b27703 100644 (file)
@@ -30,6 +30,7 @@
  * Feb 1998, Version 1.4
  * Aug 1998, Version 1.5
  * Sep 1998, Version 1.6
+ * Nov 1998, Version 1.7
  *
  * History:
  *    0.6b: first version in official kernel, Linux 1.3.46
  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
  *                   <echter@informatik.uni-rostock.de>
  *         Stephen Rothwell
+ *    1.7: Modify driver's cached copy of the disabled/disengaged flags
+ *         to reflect current state of APM BIOS.
+ *         Chris Rankin <rankinc@bellsouth.net>
+ *         Reset interrupt 0 timer to 100Hz after suspend
+ *         Chad Miller <cmiller@surfsouth.com>
+ *         Add CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+ *         Richard Gooch <rgooch@atnf.csiro.au>
+ *         Allow boot time disabling of APM
+ *         Make boot messages far less verbose by default
+ *         Make asm safer
+ *         Stephen Rothwell
  *
  * APM 1.1 Reference:
  *
@@ -167,7 +179,7 @@ extern unsigned long get_cmos_time(void);
  *
  * U: TI 4000M TravelMate: BIOS is *NOT* APM compliant
  *                         [Confirmed by TI representative]
- * U: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
+ * ?: ACER 486DX4/75: uses dseg 0040, in violation of APM specification
  *                    [Confirmed by BIOS disassembly]
  *                    [This may work now ...]
  * P: Toshiba 1950S: battery life information only gets updated after resume
@@ -214,6 +226,19 @@ extern unsigned long get_cmos_time(void);
  */
 #define APM_RELAX_SEGMENTS
 
+/*
+ * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend.
+ * This patched by Chad Miller <cmiller@surfsouth.com>, orig code by David 
+ * Chen <chen@ctpa04.mit.edu>
+ */
+#undef INIT_TIMER_AFTER_SUSPEND
+
+#ifdef INIT_TIMER_AFTER_SUSPEND
+#include <linux/timex.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#endif
+
 /*
  * Need to poll the APM BIOS every second
  */
@@ -267,13 +292,15 @@ static int                        waiting_for_resume = 0;
 
 static long                    clock_cmos_diff;
 static int                     got_clock_diff = 0;
+static int                     debug = 0;
+static int                     apm_disabled = 0;
 
 static struct wait_queue *     process_list = NULL;
 static struct apm_bios_struct *        user_list = NULL;
 
 static struct timer_list       apm_timer;
 
-static char                    driver_version[] = "1.6";       /* no spaces */
+static char                    driver_version[] = "1.7";       /* no spaces */
 
 #ifdef APM_DEBUG
 static char *  apm_event_name[] = {
@@ -393,7 +420,7 @@ static const lookup_t error_table[] = {
 #      define APM_DO_RESTORE_SEGS
 #endif
 
-static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
+static u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
        u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
 {
        unsigned int    saved_fs;
@@ -404,13 +431,17 @@ static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
        APM_DO_CLI;
        APM_DO_SAVE_SEGS;
        __asm__ __volatile__(APM_DO_ZERO_SEGS
+               "pushl %%edi\n\t"
+               "pushl %%ebp\n\t"
                "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
                "setc %%al\n\t"
+               "popl %%ebp\n\t"
+               "popl %%edi\n\t"
                APM_DO_POP_SEGS
-               :  "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
-                  "=S" (*esi)
+               : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
+                 "=S" (*esi)
                : "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-               : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc");
+               : "memory", "cc");
        APM_DO_RESTORE_SEGS;
        __restore_flags(flags);
        return *eax & 0xff;
@@ -420,7 +451,7 @@ static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
  * This version only returns one value (usually an error code)
  */
 
-static inline u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
+static u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
        u32 *eax)
 {
        u8              error;
@@ -431,13 +462,22 @@ static inline u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
        __save_flags(flags);
        APM_DO_CLI;
        APM_DO_SAVE_SEGS;
-       __asm__ __volatile__(APM_DO_ZERO_SEGS
-               "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
-               "setc %%bl\n\t"
-               APM_DO_POP_SEGS
-               : "=a" (*eax), "=b" (error)
-               : "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-               : "ax", "bx", "cx", "dx", "si", "di", "bp", "memory", "cc");
+       {
+               int     cx, dx, si;
+
+               __asm__ __volatile__(APM_DO_ZERO_SEGS
+                       "pushl %%edi\n\t"
+                       "pushl %%ebp\n\t"
+                       "lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
+                       "setc %%bl\n\t"
+                       "popl %%ebp\n\t"
+                       "popl %%edi\n\t"
+                       APM_DO_POP_SEGS
+                       : "=a" (*eax), "=b" (error), "=c" (cx), "=d" (dx),
+                         "=S" (si)
+                       : "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
+                       : "memory", "cc");
+       }
        APM_DO_RESTORE_SEGS;
        __restore_flags(flags);
        return error;
@@ -470,7 +510,7 @@ static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
        return APM_SUCCESS;
 }
 
-static inline int set_power_state(u_short what, u_short state)
+static int set_power_state(u_short what, u_short state)
 {
        u32     eax;
 
@@ -499,7 +539,6 @@ static int apm_set_display_power_state(u_short state)
 #endif
 
 #ifdef CONFIG_APM_DO_ENABLE
-/* Called by apm_setup if apm_enabled will be true. */
 static int apm_enable_power_management(void)
 {
        u32     eax;
@@ -508,6 +547,7 @@ static int apm_enable_power_management(void)
                        (apm_bios_info.version > 0x100) ? 0x0001 : 0xffff,
                        1, &eax))
                return (eax >> 8) & 0xff;
+       apm_bios_info.flags &= ~APM_BIOS_DISABLED;
        return APM_SUCCESS;
 }
 #endif
@@ -574,9 +614,10 @@ static void apm_error(char *str, int err)
        for (i = 0; i < ERROR_COUNT; i++)
                if (error_table[i].key == err) break;
        if (i < ERROR_COUNT)
-               printk(KERN_NOTICE "apm_bios: %s: %s\n", str, error_table[i].msg);
+               printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
        else
-               printk(KERN_NOTICE "apm_bios: %s: unknown error code %#2.2x\n", str, err);
+               printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
+                       str, err);
 }
 
 /* Called from console driver -- must make sure apm_enabled. */
@@ -629,7 +670,6 @@ void apm_unregister_callback(int (*callback)(apm_event_t))
        callback_list_t **      ptr;
        callback_list_t *       old;
 
-       ptr = &callback_list;
        for (ptr = &callback_list; *ptr != NULL; ptr = &(*ptr)->next)
                if ((*ptr)->callback == callback)
                        break;
@@ -663,7 +703,7 @@ static int queue_event(apm_event_t event, struct apm_bios_struct *sender)
                        static int notified;
 
                        if (notified == 0) {
-                           printk( "apm_bios: an event queue overflowed\n" );
+                           printk(KERN_ERR "apm: an event queue overflowed\n");
                            notified = 1;
                        }
                        as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS;
@@ -719,6 +759,18 @@ static void suspend(void)
        err = apm_set_power_state(APM_STATE_SUSPEND);
        if (err)
                apm_error("suspend", err);
+#ifdef INIT_TIMER_AFTER_SUSPEND
+       save_flags(flags);
+       cli();
+       /* set the clock to 100 Hz */
+       outb_p(0x34,0x43);              /* binary, mode 2, LSB/MSB, ch 0 */
+       udelay(10);
+       outb_p(LATCH & 0xff , 0x40);    /* LSB */
+       udelay(10);
+       outb(LATCH >> 8 , 0x40);        /* MSB */
+       udelay(10);
+       restore_flags(flags);
+#endif
        set_time();
 }
 
@@ -771,24 +823,27 @@ static void send_event(apm_event_t event, apm_event_t undo,
 
 static void check_events(void)
 {
-       apm_event_t     event;
+       apm_event_t             event;
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+       static unsigned long    last_resume = 0;
+       static int              did_resume = 0;
+#endif
 
        while ((event = get_event()) != 0) {
 #ifdef APM_DEBUG
                if (event <= NR_APM_EVENT_NAME)
-                       printk(KERN_DEBUG "APM BIOS received %s notify\n",
+                       printk(KERN_DEBUG "apm: received %s notify\n",
                               apm_event_name[event - 1]);
                else
-                       printk(KERN_DEBUG "APM BIOS received unknown "
+                       printk(KERN_DEBUG "apm: received unknown "
                               "event 0x%02x\n", event);
 #endif
                switch (event) {
                case APM_SYS_STANDBY:
                case APM_USER_STANDBY:
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                       if (waiting_for_resume) {
-                           return;
-                       }
+                       if (waiting_for_resume)
+                               return;
                        waiting_for_resume = 1;
 #endif
                        send_event(event, APM_STANDBY_RESUME, NULL);
@@ -803,10 +858,13 @@ static void check_events(void)
                        break;
 #endif
                case APM_SYS_SUSPEND:
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+                       if (did_resume && ((jiffies - last_resume) < HZ))
+                               break;
+#endif
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-                       if (waiting_for_resume) {
-                           return;
-                       }
+                       if (waiting_for_resume)
+                               return;
                        waiting_for_resume = 1;
 #endif
                        send_event(event, APM_NORMAL_RESUME, NULL);
@@ -819,6 +877,10 @@ static void check_events(void)
                case APM_STANDBY_RESUME:
 #ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
                        waiting_for_resume = 0;
+#endif
+#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
+                       last_resume = jiffies;
+                       did_resume = 1;
 #endif
                        set_time();
                        send_event(event, 0, NULL);
@@ -905,7 +967,7 @@ void apm_do_busy(void)
 static int check_apm_bios_struct(struct apm_bios_struct *as, const char *func)
 {
        if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-               printk(KERN_ERR "apm_bios: %s passed bad filp", func);
+               printk(KERN_ERR "apm: %s passed bad filp", func);
                return 1;
        }
        return 0;
@@ -1041,7 +1103,7 @@ static int do_release(struct inode * inode, struct file * filp)
                     as1 = as1->next)
                        ;
                if (as1 == NULL)
-                       printk(KERN_ERR "apm_bios: filp not in user list");
+                       printk(KERN_ERR "apm: filp not in user list");
                else
                        as1->next = as->next;
        }
@@ -1055,7 +1117,7 @@ static int do_open(struct inode * inode, struct file * filp)
 
        as = (struct apm_bios_struct *)kmalloc(sizeof(*as), GFP_KERNEL);
        if (as == NULL) {
-               printk(KERN_ERR "apm_bios: cannot allocate struct of size %d bytes",
+               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
                       sizeof(*as));
                return -ENOMEM;
        }
@@ -1168,6 +1230,26 @@ int apm_get_info(char *buf, char **start, off_t fpos, int length, int dummy)
 }
 #endif
 
+void __init apm_setup(char *str, int *dummy)
+{
+       int     invert;
+
+       while ((str != NULL) && (*str != '\0')) {
+               if (strncmp(str, "off", 3) == 0)
+                       apm_disabled = 1;
+               if (strncmp(str, "on", 2) == 0)
+                       apm_disabled = 0;
+               invert = (strncmp(str, "no-", 3) == 0);
+               if (invert)
+                       str += 3;
+               if (strncmp(str, "debug", 5) == 0)
+                       debug = !invert;
+               str = strchr(str, ',');
+               if (str != NULL)
+                       str += strspn(str, ", \t");
+       }
+}
+
 void __init apm_bios_init(void)
 {
        unsigned short  bx;
@@ -1178,23 +1260,18 @@ void __init apm_bios_init(void)
        char *          bat_stat;
        static struct proc_dir_entry *ent;
 
-#ifdef __SMP__
-       if (smp_num_cpus > 1) {
-               printk(KERN_NOTICE "APM disabled: APM is not SMP safe.\n");
-               return;
-       }
-#endif
        if (apm_bios_info.version == 0) {
-               printk(KERN_INFO "APM BIOS not found.\n");
+               printk(KERN_INFO "apm: BIOS not found.\n");
                return;
        }
-       printk(KERN_INFO "APM BIOS version %c.%c Flags 0x%02x (Driver version %s)\n",
-              ((apm_bios_info.version >> 8) & 0xff) + '0',
-              (apm_bios_info.version & 0xff) + '0',
-              apm_bios_info.flags,
-              driver_version);
+       printk(KERN_INFO
+               "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n",
+               ((apm_bios_info.version >> 8) & 0xff),
+               (apm_bios_info.version & 0xff),
+               apm_bios_info.flags,
+               driver_version);
        if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) {
-               printk(KERN_INFO "    No 32 bit BIOS support\n");
+               printk(KERN_INFO "apm: no 32 bit BIOS support\n");
                return;
        }
 
@@ -1209,14 +1286,28 @@ void __init apm_bios_init(void)
        if (apm_bios_info.version < 0x102)
                apm_bios_info.cseg_16_len = 0xFFFF; /* 64k */
 
-       printk(KERN_INFO "    Entry %x:%lx cseg16 %x dseg %x",
-              apm_bios_info.cseg, apm_bios_info.offset,
-              apm_bios_info.cseg_16, apm_bios_info.dseg);
-       if (apm_bios_info.version > 0x100)
-               printk(" cseg len %x, cseg16 len %x, dseg len %x",
-                      apm_bios_info.cseg_len, apm_bios_info.cseg_16_len,
-                      apm_bios_info.dseg_len);
-       printk("\n");
+       if (debug) {
+               printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x",
+                       apm_bios_info.cseg, apm_bios_info.offset,
+                       apm_bios_info.cseg_16, apm_bios_info.dseg);
+               if (apm_bios_info.version > 0x100)
+                       printk(" cseg len %x, cseg16 len %x, dseg len %x",
+                               apm_bios_info.cseg_len,
+                               apm_bios_info.cseg_16_len,
+                               apm_bios_info.dseg_len);
+               printk("\n");
+       }
+
+       if (apm_disabled) {
+               printk(KERN_NOTICE "apm: disabled on user request.\n");
+               return;
+       }
+#ifdef __SMP__
+       if (smp_num_cpus > 1) {
+               printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+               return;
+       }
+#endif
 
        /*
         * Set up a segment that references the real mode segment 0x40
@@ -1253,74 +1344,78 @@ void __init apm_bios_init(void)
                set_limit(gdt[APM_CS_16 >> 3], apm_bios_info.cseg_16_len);
                set_limit(gdt[APM_DS >> 3], apm_bios_info.dseg_len);
 #endif
-               /* The APM 1.2 docs state that the apm_driver_version
-                * call can fail if we try to connect as 1.2 to a 1.1 bios.
+               /*
+                * We only support BIOSs up to version 1.2
                 */
-               apm_bios_info.version = 0x0102;
-               error = apm_driver_version(&apm_bios_info.version);
-               if (error != APM_SUCCESS) { /* Fall back to an APM 1.1 connection. */
-                       apm_bios_info.version = 0x0101;
-                       error = apm_driver_version(&apm_bios_info.version);
-               }
-               if (error != APM_SUCCESS) /* Fall back to an APM 1.0 connection. */
+               if (apm_bios_info.version > 0x0102)
+                       apm_bios_info.version = 0x0102;
+               if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) {
+                       /* Fall back to an APM 1.0 connection. */
                        apm_bios_info.version = 0x100;
-               else {
-                       apm_engage_power_management(0x0001);
-                       printk( "    Connection version %d.%d\n",
-                               (apm_bios_info.version >> 8) & 0xff,
-                               apm_bios_info.version & 0xff );
                }
        }
-
-       error = apm_get_power_status(&bx, &cx, &dx);
-       if (error)
-               printk(KERN_INFO "    Power status not available\n");
-       else {
-               switch ((bx >> 8) & 0xff) {
-               case 0: power_stat = "off line"; break;
-               case 1: power_stat = "on line"; break;
-               case 2: power_stat = "on backup power"; break;
-               default: power_stat = "unknown"; break;
-               }
-               switch (bx & 0xff) {
-               case 0: bat_stat = "high"; break;
-               case 1: bat_stat = "low"; break;
-               case 2: bat_stat = "critical"; break;
-               case 3: bat_stat = "charging"; break;
-               default: bat_stat = "unknown"; break;
-               }
-               printk(KERN_INFO "    AC %s, battery status %s, battery life ",
-                      power_stat, bat_stat);
-               if ((cx & 0xff) == 0xff)
-                       printk("unknown\n");
-               else
-                       printk("%d%%\n", cx & 0xff);
-               if (apm_bios_info.version > 0x100) {
-                       printk("    battery flag 0x%02x, battery life ",
-                              (cx >> 8) & 0xff);
-                       if (dx == 0xffff)
+       if (debug) {
+               printk(KERN_INFO "apm: onnection version %d.%d\n",
+                       (apm_bios_info.version >> 8) & 0xff,
+                       apm_bios_info.version & 0xff );
+
+               error = apm_get_power_status(&bx, &cx, &dx);
+               if (error)
+                       printk(KERN_INFO "apm: power status not available\n");
+               else {
+                       switch ((bx >> 8) & 0xff) {
+                       case 0: power_stat = "off line"; break;
+                       case 1: power_stat = "on line"; break;
+                       case 2: power_stat = "on backup power"; break;
+                       default: power_stat = "unknown"; break;
+                       }
+                       switch (bx & 0xff) {
+                       case 0: bat_stat = "high"; break;
+                       case 1: bat_stat = "low"; break;
+                       case 2: bat_stat = "critical"; break;
+                       case 3: bat_stat = "charging"; break;
+                       default: bat_stat = "unknown"; break;
+                       }
+                       printk(KERN_INFO "apm: AC %s, battery status %s, battery life ",
+                              power_stat, bat_stat);
+                       if ((cx & 0xff) == 0xff)
                                printk("unknown\n");
-                       else {
-                               if ((dx & 0x8000))
-                                       printk("%d minutes\n", dx & 0x7ffe );
-                               else
-                                       printk("%d seconds\n", dx & 0x7fff );
+                       else
+                               printk("%d%%\n", cx & 0xff);
+                       if (apm_bios_info.version > 0x100) {
+                               printk("apm: battery flag 0x%02x, battery life ",
+                                      (cx >> 8) & 0xff);
+                               if (dx == 0xffff)
+                                       printk("unknown\n");
+                               else {
+                                       if ((dx & 0x8000))
+                                               printk("%d minutes\n", dx & 0x7ffe );
+                                       else
+                                               printk("%d seconds\n", dx & 0x7fff );
+                               }
                        }
                }
        }
 
 #ifdef CONFIG_APM_DO_ENABLE
-       /*
-        * This call causes my NEC UltraLite Versa 33/C to hang if it is
-        * booted with PM disabled but not in the docking station.
-        * Unfortunate ...
-        */
-       error = apm_enable_power_management();
-       if (error)
-               apm_error("enable power management", error);
-       if (error == APM_DISABLED)
-               return;
+       if (apm_bios_info.flags & APM_BIOS_DISABLED) {
+               /*
+                * This call causes my NEC UltraLite Versa 33/C to hang if it
+                * is booted with PM disabled but not in the docking station.
+                * Unfortunate ...
+                */
+               error = apm_enable_power_management();
+               if (error) {
+                       apm_error("enable power management", error);
+                       return;
+               }
+       }
 #endif
+       if (((apm_bios_info.flags & APM_BIOS_DISABLED) == 0)
+           && (apm_bios_info.version > 0x0100)) {
+               if (apm_engage_power_management(0x0001) == APM_SUCCESS)
+                       apm_bios_info.flags &= ~APM_BIOS_DISENGAGED;
+       }
 
        init_timer(&apm_timer);
        apm_timer.function = do_apm_timer;
index 4ddefa931b2e7fef16042bb7097e7919e6e2ab12..00f39d4ed5ed84d325dd403396b3866a041fc26e 100644 (file)
@@ -102,44 +102,25 @@ static void hard_idle(void)
 
 /*
  * The idle loop on a uniprocessor i386..
- */
-asmlinkage int sys_idle(void)
+ */ 
+static int cpu_idle(void *unused)
 {
-        unsigned long start_idle = 0;
-       int ret = -EPERM;
+       unsigned long start_idle = jiffies;
 
-       lock_kernel();
-       if (current->pid != 0)
-               goto out;
        /* endless idle loop with no priority at all */
-       current->priority = 0;
-       current->counter = 0;
        for (;;) {
-               /*
-                *      We are locked at this point. So we can safely call
-                *      the APM bios knowing only one CPU at a time will do
-                *      so.
-                */
-               if (!start_idle) {
-                       check_pgt_cache();
-                       start_idle = jiffies;
-               }
                if (jiffies - start_idle > HARD_IDLE_TIMEOUT) 
                        hard_idle();
                else  {
                        if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
                                __asm__("hlt");
                }
-               run_task_queue(&tq_scheduler);
                if (current->need_resched) 
-                       start_idle = 0;
+                       start_idle = jiffies;
+               current->policy = SCHED_YIELD;
                schedule();
+               check_pgt_cache();
        }
-       ret = 0;
-out:
-       unlock_kernel();
-       return ret;
 }
 
 #else
@@ -150,21 +131,19 @@ out:
 
 int cpu_idle(void *unused)
 {
-       current->priority = 0;
-       while(1)
-       {
-               if(current_cpu_data.hlt_works_ok &&
-                               !hlt_counter && !current->need_resched)
-                       __asm("hlt");
-               check_pgt_cache();
-               run_task_queue(&tq_scheduler);
 
-               /* endless idle loop with no priority at all */
-               current->counter = 0;
+       /* endless idle loop with no priority at all */
+       while(1) {
+               if (current_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
+                       __asm__("hlt");
+               current->policy = SCHED_YIELD;
                schedule();
+               check_pgt_cache();
        }
 }
 
+#endif
+
 asmlinkage int sys_idle(void)
 {
        if (current->pid != 0)
@@ -173,8 +152,6 @@ asmlinkage int sys_idle(void)
        return 0;
 }
 
-#endif
-
 /*
  * This routine reboots the machine by asking the keyboard
  * controller to pulse the reset-line low. We try that for a while,
@@ -509,23 +486,27 @@ void release_segments(struct mm_struct *mm)
  */
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-       long retval;
+       long retval, d0;
 
        __asm__ __volatile__(
                "movl %%esp,%%esi\n\t"
                "int $0x80\n\t"         /* Linux/i386 system call */
                "cmpl %%esp,%%esi\n\t"  /* child or parent? */
                "je 1f\n\t"             /* parent - jump */
-               "pushl %3\n\t"          /* push argument */
-               "call *%4\n\t"          /* call fn */
-               "movl %2,%0\n\t"        /* exit */
+               /* Load the argument into eax, and push it.  That way, it does
+                * not matter whether the called function is compiled with
+                * -mregparm or not.  */
+               "movl %4,%%eax\n\t"
+               "pushl %%eax\n\t"               
+               "call *%5\n\t"          /* call fn */
+               "movl %3,%0\n\t"        /* exit */
                "int $0x80\n"
                "1:\t"
-               :"=a" (retval)
+               :"=&a" (retval), "=&S" (d0)
                :"0" (__NR_clone), "i" (__NR_exit),
                 "r" (arg), "r" (fn),
                 "b" (flags | CLONE_VM)
-               :"si");
+               : "memory");
        return retval;
 }
 
index e6ed37c3b330250f8dec5a73a6d4e6201867a763..c0aa02d6695663dc03d80ef7c9db0e3bf493c141 100644 (file)
@@ -592,7 +592,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
 {
        siginfo_t info;
        struct k_sigaction *ka;
index 5b3908cddf4a496e191348c689f20e64e45df3d7..d181dc6994bd5246684bc2101de444fbd8e67a71 100644 (file)
@@ -63,7 +63,7 @@
 #define VM86_REGS_SIZE2 (sizeof(struct kernel_vm86_regs) - VM86_REGS_SIZE1)
 
 asmlinkage struct pt_regs * FASTCALL(save_v86_state(struct kernel_vm86_regs * regs));
-asmlinkage struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
+struct pt_regs * save_v86_state(struct kernel_vm86_regs * regs)
 {
        struct pt_regs *ret;
        unsigned long tmp;
index aed7ecc559179ab8b614727b35502f456c1bcd45..693072b1a5d54c50c2f31ecfeabc2f18dabdfaee 100644 (file)
@@ -293,11 +293,18 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
                 * extended bios data area. 
                 *
                 * there is a real-mode segmented pointer pointing to the
-                * 4K EBDA area at 0x40E, calculate and scan it here:
+                * 4K EBDA area at 0x40E, calculate and scan it here.
+                *
+                * NOTE! There are Linux loaders that will corrupt the EBDA
+                * area, and as such this kind of SMP config may be less
+                * trustworthy, simply because the SMP table may have been
+                * stomped on during early boot.
                 */
                address = *(unsigned short *)phys_to_virt(0x40E);
                address<<=4;
                smp_scan_config(address, 0x1000);
+               if (smp_found_config)
+                       printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.rutgers.edu if you experience SMP problems!\n");
        }
 #endif
        start_mem = PAGE_ALIGN(start_mem);
index 740f4551fbbb9616f0bdb651ff509e31f7c05f08..28250b0bd20649d185f73277ab6748818498b80b 100644 (file)
@@ -84,11 +84,16 @@ static int remap_area_pages(unsigned long address, unsigned long phys_addr,
  * Remap an arbitrary physical address space into the kernel virtual
  * address space. Needed when the kernel wants to access high addresses
  * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
  */
 void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
        void * addr;
        struct vm_struct * area;
+       unsigned long offset;
 
        /*
         * Don't remap the low PCI/ISA area, it's always mapped..
@@ -105,9 +110,9 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
        /*
         * Mappings have to be page-aligned
         */
-       if (phys_addr & ~PAGE_MASK)
-               return NULL;
-       size = PAGE_ALIGN(size);
+       offset = phys_addr & ~PAGE_MASK;
+       phys_addr &= PAGE_MASK;
+       size = PAGE_ALIGN(size + offset);
 
        /*
         * Don't allow mappings that wrap..
@@ -126,11 +131,11 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag
                vfree(addr);
                return NULL;
        }
-       return addr;
+       return (void *) (offset + (char *)addr);
 }
 
 void iounmap(void *addr)
 {
        if (addr > high_memory)
-               return vfree(addr);
+               return vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
index 65d2f77477f7845e3887e7c1693200fab3de4a5d..38042ee458f63f0af6115063dd740b181052dbb1 100644 (file)
@@ -201,7 +201,12 @@ void handle_scancode(unsigned char scancode)
        add_keyboard_randomness(scancode);
 
        tty = ttytab? ttytab[fg_console]: NULL;
-       kbd = kbd_table + fg_console;
+       if (tty && (!tty->driver_data)) {
+               /* This is to workaround ugly bug in tty_io.c, which
+                   does not do locking when it should */
+               tty = NULL;
+       }
+       kbd = kbd_table + fg_console;
        if ((raw_mode = (kbd->kbdmode == VC_RAW))) {
                put_queue(scancode);
                /* we do not return yet, because we want to maintain
index baec5e4cb11df6db24e7467b08ffc1d0d4e424da..ae769f6195702f3f7f0fbbe506506425c4752b94 100644 (file)
  * Parport sharing hacking by Andrea Arcangeli
  * Fixed kernel_(to/from)_user memory copy to check for errors
  *                             by Riccardo Facchetti <fizban@tin.it>
- * Interrupt handling workaround for printers with buggy handshake
- *                             by Andrea Arcangeli, 11 May 98
+ * Redesigned interrupt handling for handle printers with buggy handshake
+ *                             by Andrea Arcangeli, 11 May 1998
+ * Full efficient handling of printer with buggy irq handshake (now I have
+ * understood the meaning of the strange handshake). This is done sending new
+ * characters if the interrupt is just happened, even if the printer say to
+ * be still BUSY. This is needed at least with Epson Stylus Color. To enable
+ * the new TRUST_IRQ mode read the `LP OPTIMIZATION' section below...
+ * Fixed the irq on the rising edge of the strobe case.
+ * Obsoleted the CAREFUL flag since a printer that doesn' t work with
+ * CAREFUL will block a bit after in lp_check_status().
+ *                             Andrea Arcangeli, 15 Oct 1998
  */
 
 /* This driver should, in theory, work with any parallel port that has an
  *     # insmod lp.o reset=1
  */
 
+/*
+ * LP OPTIMIZATIONS
+ *
+ * - TRUST_IRQ flag
+ * 
+ * Epson Stylus Color, HP and many other new printers want the TRUST_IRQ flag
+ * set when printing with interrupts. This is a long story. Such printers
+ * use a broken handshake (see the timing graph below) when printing with
+ * interrupts. The lp driver as default is just able to handle such bogus
+ * handshake, but setting such flag cause lp to go faster and probably do
+ * what such printers want (even if not documented).
+ *
+ * NOTE that setting the TRUST_IRQ flag in some printer can cause the irq
+ * printing to fail completly. You must try, to know if your printer
+ * will handle it. I suggest a graphics printing to force a major flow of
+ * characters to the printer for do the test. NOTE also that the TRUST_IRQ
+ * flag _should_ be fine everywhere but there is a lot of buggy hardware out
+ * there, so I am forced to implement it as a not-default thing.
+ * WARNING: before to do the test, be sure to have not played with the
+ * `-w' parameter of tunelp!
+ *
+ * Note also that lp automagically warn you (with a KERN_WARNING) if it
+ * detects that you could _try_ to set the TRUST_IRQ flag to speed up the
+ * printing and decrease the CPU load.
+ *
+ * To set the TRUST_IRQ flag you can use this command:
+ *
+ * tunelp /dev/lp? -T on
+ *
+ * If you have an old tunelp executable you can (hack and) use this simple
+ * C lazy proggy to set the flag in the lp driver:
+
+-------------------------- cut here -------------------------------------
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#define        LPTRUSTIRQ  0x060f
+
+int main(int argc, char **argv)
+{
+       int fd = open("/dev/lp0", O_RDONLY);
+       ioctl(fd, LPTRUSTIRQ, argc - 1);
+       if (argc - 1)
+               printf("trusting the irq\n");
+       else
+               printf("untrusting the irq\n");
+       return 0;
+}
+-------------------------- cut here -------------------------------------
+
+ * - LP_WAIT time
+ *
+ * You can use this setting if your printer is fast enough and/or your
+ * machine is slow enough ;-).
+ *
+ * tunelp /dev/lp? -w 0
+ *
+ * - LP_CHAR tries
+ *
+ * If you print with irqs probably you can decrease the CPU load a lot using
+ * this setting. This is not the default because the printing is reported to
+ * be jerky somewhere...
+ *
+ * tunelp /dev/lp? -c 1
+ *
+ *                                     11 Nov 1998, Andrea Arcangeli
+ */
+
 /* COMPATIBILITY WITH OLD KERNELS
  *
  * Under Linux 2.0 and previous versions, lp devices were bound to ports at
  *     ftp://e-mind.com/pub/linux/pscan/
  *
  *                                     11 May 98, Andrea Arcangeli
+ *
+ * My printer scanner run on an Epson Stylus Color show that such printer
+ * generates the irq on the _rising_ edge of the STROBE. Now lp handle
+ * this case fine too.
+ *
+ *                                     15 Oct 1998, Andrea Arcangeli
  */
 
 #include <linux/module.h>
 
 #include <linux/parport.h>
 #undef LP_STATS
-#undef LP_NEED_CAREFUL
 #include <linux/lp.h>
 
 #include <asm/irq.h>
@@ -115,16 +197,14 @@ struct lp_struct lp_table[LP_NO] =
                           NULL, 0, 0, 0}
 };
 
-/* Test if printer is ready (and optionally has no error conditions) */
-#ifdef LP_NEED_CAREFUL
-#define LP_READY(minor, status) \
-  ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : ((status) & LP_PBUSY))
-#define _LP_CAREFUL_READY(status) \
-   ((status) & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
-      (LP_PBUSY|LP_PSELECD|LP_PERRORP)
-#else
-#define LP_READY(minor, status) ((status) & LP_PBUSY)
-#endif
+/* Test if printer is ready */
+#define        LP_READY(status)        ((status) & LP_PBUSY)
+/* Test if the printer is not acking the strobe */
+#define        LP_NO_ACKING(status)    ((status) & LP_PACK)
+/* Test if the printer has error conditions */
+#define LP_NO_ERROR(status)                                    \
+        (((status) & (LP_POUTPA|LP_PSELECD|LP_PERRORP)) ==     \
+        (LP_PSELECD|LP_PERRORP))
 
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
@@ -187,60 +267,124 @@ static int lp_reset(int minor)
        return retval;
 }
 
+#define        lp_wait(minor)  udelay(LP_WAIT(minor))
+
 static inline int lp_char(char lpchar, int minor)
 {
-       unsigned int wait = 0;
        unsigned long count = 0;
 #ifdef LP_STATS
        struct lp_stats *stats;
 #endif
 
+       if (signal_pending(current))
+               return 0;
+
        for (;;)
        {
+               unsigned char status;
+               int irq_ok = 0;
+
+               /*
+                * Give a chance to other pardevice to run in the meantime.
+                */
                lp_yield(minor);
-               if (LP_READY(minor, r_str(minor)))
-                       break;
-               if (++count == LP_CHAR(minor) || signal_pending(current))
-                       return 0;
+
+               status = r_str(minor);
+               if (LP_NO_ERROR(status))
+               {
+                       if (LP_READY(status))
+                               break;
+
+                       /*
+                        * This is a crude hack that should be well known
+                        * at least by Epson device driver developers. -arca
+                        */
+                       irq_ok = (!LP_POLLED(minor) &&
+                                 LP_NO_ACKING(status) &&
+                                 lp_table[minor].irq_detected);
+                       if ((LP_F(minor) & LP_TRUST_IRQ) && irq_ok)
+                               break;
+               }
+               /*
+                * NOTE: if you run with irqs you _must_ use
+                * `tunelp /dev/lp? -c 1' to be rasonable efficient!
+                */
+               if (++count == LP_CHAR(minor))
+               {
+                       if (irq_ok)
+                       {
+                               static int first_time = 1;
+                               /*
+                                * The printer is using a buggy handshake, so
+                                * revert to polling to not overload the
+                                * machine and warn the user that its printer
+                                * could get optimized trusting the irq. -arca
+                                */
+                               lp_table[minor].irq_missed = 1;
+                               if (first_time)
+                               {
+                                       first_time = 0;
+                                       printk(KERN_WARNING "lp%d: the "
+                                              "printing could be optimized "
+                                              "using the TRUST_IRQ flag, "
+                                              "see the top of "
+                                              "linux/drivers/char/lp.c\n",
+                                              minor);
+                               }
+                       }
+                       return 0;
+               }
        }
 
        w_dtr(minor, lpchar);
+
 #ifdef LP_STATS
        stats = &LP_STAT(minor);
        stats->chars++;
 #endif
+
        /* must wait before taking strobe high, and after taking strobe
           low, according spec.  Some printers need it, others don't. */
-#ifndef __sparc__
-       while (wait != LP_WAIT(minor)) /* FIXME: should be a udelay() */
-               wait++;
-#else
-       udelay(1);
-#endif
+       lp_wait(minor);
+
        /* control port takes strobe high */
-       w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
-#ifndef __sparc__
-       while (wait)                    /* FIXME: should be a udelay() */
-               wait--;
-#else
-       udelay(1);
-#endif
-       /* take strobe low */
        if (LP_POLLED(minor))
-               /* take strobe low */
-               w_ctr(minor, LP_PSELECP | LP_PINITP);
-       else
        {
+               w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE);
+               lp_wait(minor);
+               w_ctr(minor, LP_PSELECP | LP_PINITP);
+       } else {
+               /*
+                * Epson Stylus Color generate the IRQ on the rising edge of
+                * strobe so clean the irq's information before playing with
+                * the strobe. -arca
+                */
                lp_table[minor].irq_detected = 0;
                lp_table[minor].irq_missed = 0;
+               /*
+                * Be sure that the CPU doesn' t reorder instructions. -arca
+                */
+               mb();
+               w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PSTROBE | LP_PINTEN);
+               lp_wait(minor);
                w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
        }
 
+       /*
+        * Give to the printer a chance to put BUSY low. Really we could
+        * remove this because we could _guess_ that we are slower to reach
+        * again lp_char() than the printer to put BUSY low, but I' d like
+        * to remove this variable from the function I go solve
+        * when I read bug reports ;-). -arca
+        */
+       lp_wait(minor);
+
 #ifdef LP_STATS
        /* update waittime statistics */
        if (count > stats->maxwait) {
 #ifdef LP_DEBUG
-               printk(KERN_DEBUG "lp%d success after %d counts.\n", minor, count);
+               printk(KERN_DEBUG "lp%d success after %d counts.\n",
+                      minor, count);
 #endif
                stats->maxwait = count;
        }
@@ -325,7 +469,10 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
        lp_table[minor].irq_detected = 0;
        lp_table[minor].irq_missed = 1;
 
-       w_ctr(minor, LP_PSELECP | LP_PINITP);
+       if (LP_POLLED(minor))
+               w_ctr(minor, LP_PSELECP | LP_PINITP);
+       else
+               w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
 
        do {
                bytes_written = 0;
@@ -396,9 +543,7 @@ static int lp_write_buf(unsigned int minor, const char *buf, int count)
                                                goto lp_polling;
                                        }
                                        if (!lp_table[minor].irq_detected)
-                                       {
                                                interruptible_sleep_on_timeout(&lp->wait_q, LP_TIMEOUT_INTERRUPT);
-                                       }
                                        sti();
                                }
                        }
@@ -453,101 +598,97 @@ static int lp_read_nibble(int minor)
        return (i & 0x0f);
 }
 
-static inline void lp_select_in_high(int minor) 
-{
-       parport_frob_control(lp_table[minor].dev->port, 8, 8);
+static void lp_read_terminate(struct parport *port) {
+       parport_write_control(port, (parport_read_control(port) & ~2) | 8);
+       /* SelectIN high, AutoFeed low */
+       if (parport_wait_peripheral(port, 0x80, 0)) 
+               /* timeout, SelectIN high, Autofeed low */
+               return;
+       parport_write_control(port, parport_read_control(port) | 2);
+       /* AutoFeed high */
+       parport_wait_peripheral(port, 0x80, 0x80);
+       /* no timeout possible, Autofeed low, SelectIN high */
+       parport_write_control(port, (parport_read_control(port) & ~2) | 8);
 }
 
 /* Status readback confirming to ieee1284 */
 static ssize_t lp_read(struct file * file, char * buf,
-                      size_t count, loff_t *ppos)
+                      size_t length, loff_t *ppos)
 {
-       unsigned char z=0, Byte=0, status;
-       char *temp;
-       ssize_t retval;
-       unsigned int counter=0;
-       unsigned int i;
+       int i;
        unsigned int minor=MINOR(file->f_dentry->d_inode->i_rdev);
-       
-       /* Claim Parport or sleep until it becomes available
-        */
-       lp_parport_claim (minor);
+       char *temp = buf;
+       ssize_t count = 0;
+       unsigned char z = 0;
+       unsigned char Byte = 0;
+       struct parport *port = lp_table[minor].dev->port;
 
-       temp=buf;       
-#ifdef LP_READ_DEBUG 
-       printk(KERN_INFO "lp%d: read mode\n", minor);
-#endif
+       lp_parport_claim (minor);
 
-       retval = verify_area(VERIFY_WRITE, buf, count);
-       if (retval)
-               return retval;
-       if (parport_ieee1284_nibble_mode_ok(lp_table[minor].dev->port, 0)==0) {
-#ifdef LP_READ_DEBUG
-               printk(KERN_INFO "lp%d: rejected IEEE1284 negotiation.\n",
-                      minor);
-#endif
-               lp_select_in_high(minor);
-               parport_release(lp_table[minor].dev);
-               return temp-buf;          /*  End of file */
+       switch (parport_ieee1284_nibble_mode_ok(port, 0))
+       {
+       case 0:
+               /* Handshake failed. */
+               lp_read_terminate(port);
+               lp_parport_release (minor);
+               return -EIO;
+       case 1:
+               /* No data. */
+               lp_read_terminate(port);
+               lp_parport_release (minor);
+               return 0;
+       default:
+               /* Data available. */
+
+               /* Hack: Wait 10ms (between events 6 and 7) */
+                schedule_timeout((HZ+99)/100);
+                break;
        }
-       for (i=0; i<=(count*2); i++) {
-               parport_frob_control(lp_table[minor].dev->port, 2, 2); /* AutoFeed high */
-               do {
-                       status = (r_str(minor) & 0x40);
-                       udelay(50);
-                       counter++;
-                       if (current->need_resched)
-                               schedule ();
-               } while ((status == 0x40) && (counter < 20));
-               if (counter == 20) { 
-                       /* Timeout */
+
+       for (i=0; ; i++) {
+               parport_frob_control(port, 2, 2); /* AutoFeed high */
+               if (parport_wait_peripheral(port, 0x40, 0)) {
 #ifdef LP_READ_DEBUG
-                       printk(KERN_DEBUG "lp_read: (Autofeed high) timeout\n");
+                       /* Some peripherals just time out when they've sent
+                          all their data.  */
+                       printk("%s: read1 timeout.\n", port->name);
 #endif
-                       parport_frob_control(lp_table[minor].dev->port, 2, 0);
-                       lp_select_in_high(minor);
-                       parport_release(lp_table[minor].dev);
-                       return temp-buf; /* end the read at timeout */
+                       parport_frob_control(port, 2, 0); /* AutoFeed low */
+                       break;
                }
-               counter=0;
                z = lp_read_nibble(minor);
-               parport_frob_control(lp_table[minor].dev->port, 2, 0); /* AutoFeed low */
-               do {
-                       status=(r_str(minor) & 0x40);
-                       udelay(20);
-                       counter++;
-                       if (current->need_resched)
-                               schedule ();
-               } while ( (status == 0) && (counter < 20) );
-               if (counter == 20) { /* Timeout */
-#ifdef LP_READ_DEBUG
-                       printk(KERN_DEBUG "lp_read: (Autofeed low) timeout\n");
-#endif
-                       if (signal_pending(current)) {
-                               lp_select_in_high(minor);
-                               parport_release(lp_table[minor].dev);
-                               if (temp !=buf)
-                                       return temp-buf;
-                               else 
-                                       return -EINTR;
-                       }
-                       current->state=TASK_INTERRUPTIBLE;
-                       schedule_timeout(LP_TIME(minor));
+               parport_frob_control(port, 2, 0); /* AutoFeed low */
+               if (parport_wait_peripheral(port, 0x40, 0x40)) {
+                       printk("%s: read2 timeout.\n", port->name);
+                       break;
                }
+               if ((i & 1) != 0) {
+                       Byte |= (z<<4);
+                       if (temp) {
+                               if (__put_user (Byte, temp))
+                               {
+                                       count = -EFAULT;
+                                       temp = NULL;
+                               } else {
+                                       temp++;
 
-               counter=0;
-
-               if (( i & 1) != 0) {
-                       Byte= (Byte | z<<4);
-                       if (__put_user(Byte, (char *)temp))
-                               return -EFAULT;
-                       temp++;
-               } else Byte=z;
+                                       if (++count == length)
+                                               temp = NULL;
+                               }
+                       }
+                       /* Does the error line indicate end of data? */
+                       if ((parport_read_status(port) & LP_PERRORP) == 
+                           LP_PERRORP) 
+                               break;
+               } else 
+                       Byte=z;
        }
 
-       lp_select_in_high(minor);
-       lp_parport_release(minor);
-       return temp-buf;        
+       lp_read_terminate(port);
+
+       lp_parport_release (minor);
+
+       return count;
 }
 
 #endif
@@ -645,7 +786,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        else
                                LP_F(minor) &= ~LP_ABORTOPEN;
                        break;
-#ifdef LP_NEED_CAREFUL
+#ifdef OBSOLETED
                case LPCAREFUL:
                        if (arg)
                                LP_F(minor) |= LP_CAREFUL;
@@ -653,6 +794,12 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                                LP_F(minor) &= ~LP_CAREFUL;
                        break;
 #endif
+               case LPTRUSTIRQ:
+                       if (arg)
+                               LP_F(minor) |= LP_TRUST_IRQ;
+                       else
+                               LP_F(minor) &= ~LP_TRUST_IRQ;
+                       break;
                case LPWAIT:
                        LP_WAIT(minor) = arg;
                        break;
@@ -696,7 +843,6 @@ static int lp_ioctl(struct inode *inode, struct file *file,
        return retval;
 }
 
-
 static struct file_operations lp_fops = {
        lp_lseek,
 #ifdef CONFIG_PRINTER_READBACK
index 6fe15f239d054910c6507c96325825eb9af9f59a..ee2e7e099a2765acf9a6aedc8e96193860925bd0 100644 (file)
@@ -868,7 +868,13 @@ static int init_dev(kdev_t device, struct tty_struct **ret_tty)
         * Failures after this point use release_mem to clean up, so 
         * there's no need to null out the local pointers.
         */
-       driver->table[idx] = tty;
+       driver->table[idx] = tty;       /* FIXME: this is broken and
+       probably causes ^D bug. tty->private_date does not (yet) point
+       to a console, if keypress comes now, await armagedon. 
+
+       also, driver->table is accessed from interrupt for vt case,
+       and this does not look like atomic access at all. */
+       
        if (!*tp_loc)
                *tp_loc = tp;
        if (!*ltp_loc)
index c3a2550d198f560fadaed59485097f4c6b409652..e7af08c0cf3a948a8b97b70963f50620ca27bb74 100644 (file)
@@ -1,3 +1,19 @@
+Thu Nov 26  22:00 1998 Gerard Roudier (groudier@club-internet.fr)
+       * revision 3.1d
+       - The SISL RAID change requires now remap_pci_mem() stuff to be 
+         compiled for __i386__ when normal IOs are used.
+       - Minor spelling fixes in doc files.
+
+Sat Nov 21  18:00 1998 Gerard Roudier (groudier@club-internet.fr)
+       * revision 3.1c
+       - Ignore chips that are driven by SISL RAID (DAC 960).
+         Change sent by Leonard Zubkoff and slightly reworked.
+       - Still a buglet in the tags initial settings that needed to be fixed.
+         It was not possible to disable TGQ at system startup for devices 
+         that claim TGQ support. The driver used at least 2 for the queue 
+         depth but did'nt keep track of user settings for tags depth lower 
+         than 2.
+
 Wed Nov 11  10:00 1998 Gerard Roudier (groudier@club-internet.fr)
        * revision 3.1b
        - The driver was unhappy when configured with default_tags > MAX_TAGS
index eb11ccb39fb21843fc830ebdcff409413f1872f3..409967d0ee6c75e0a6b59d705d8c28431dd1342d 100644 (file)
@@ -4,7 +4,7 @@ Written by Gerard Roudier <groudier@club-internet.fr>
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-18 October 1998
+22 November 1998
 ===============================================================================
 
 1.  Introduction
@@ -853,7 +853,7 @@ SCSI_NCR_SETUP_SPECIAL_FEATURES     (default: defined)
         For 810A, 860, 825A, 875 and 895 scsi chips, this option enables 
        support of features that reduce load of PCI bus and memory accesses 
        during  scsi transfer processing: burst op-code fetch, read multiple, 
-        read line, prefetch, cache line line, write and invalidate, 
+        read line, prefetch, cache line, write and invalidate, 
         burst 128 (875 only), large dma fifo (875 only), offset 16 (875 only).
        Can be changed by the following boot setup command:
                ncr53c8xx=specf:n
index dbfe1b17767603f226737efea2338eef359283bd..7057b75359ea3932801c9669a5bfad1ce9d22638 100644 (file)
@@ -73,7 +73,7 @@
 */
 
 /*
-**     November 11 1998, version 3.1b
+**     November 26 1998, version 3.1d
 **
 **     Supported SCSI-II features:
 **         Synchronous negotiation
@@ -582,7 +582,7 @@ static spinlock_t driver_lock;
 #define bus_dvma_to_mem(p)             (p)
 #endif
 
-#ifndef NCR_IOMAPPED
+#if defined(__i386__) || !defined(NCR_IOMAPPED)
 __initfunc(
 static vm_offset_t remap_pci_mem(u_long base, u_long size)
 )
@@ -601,7 +601,7 @@ static void unmap_pci_mem(vm_offset_t vaddr, u_long size)
        if (vaddr)
                iounmap((void *) (vaddr & PAGE_MASK));
 }
-#endif /* !NCR_IOMAPPED */
+#endif /* __i386__ || !NCR_IOMAPPED */
 
 /*
 **     Insert a delay in micro-seconds and milli-seconds.
@@ -2145,7 +2145,6 @@ static    void    ncr_script_copy_and_bind
                                (ncb_p np, ncrcmd *src, ncrcmd *dst, int len);
 static  void    ncr_script_fill (struct script * scr, struct scripth * scripth);
 static int     ncr_scatter     (ccb_p cp, Scsi_Cmnd *cmd);
-static void    ncr_setmaxtags  (ncb_p np, tcb_p tp, u_long numtags);
 static void    ncr_getsync     (ncb_p np, u_char sfac, u_char *fakp, u_char *scntl3p);
 static void    ncr_setsync     (ncb_p np, ccb_p cp, u_char scntl3, u_char sxfer);
 static void    ncr_setup_tags  (ncb_p np, u_char tn, u_char ln);
@@ -5837,7 +5836,7 @@ void ncr_complete (ncb_p np, ccb_p cp)
                **      If tags was reduced due to queue full,
                **      increase tags if 1000 good status received.
                */
-               if (lp && lp->numtags < lp->maxtags) {
+               if (lp && lp->usetags && lp->numtags < lp->maxtags) {
                        ++lp->num_good;
                        if (lp->num_good >= 1000) {
                                lp->num_good = 0;
@@ -6537,24 +6536,6 @@ static void ncr_setwide (ncb_p np, ccb_p cp, u_char wide, u_char ack)
 **==========================================================
 */
 
-static void ncr_setmaxtags (ncb_p np, tcb_p tp, u_long numtags)
-{
-       if (numtags > tp->usrtags)
-               numtags = tp->usrtags;
-
-       if (tp) {
-               int ln;
-               for (ln = 0; ln < MAX_LUN; ln++) {
-                       lcb_p lp = tp->lp[ln];
-
-                       if (!lp)
-                               continue;
-                       lp->maxtags = lp->numtags = numtags;
-                       ncr_setup_tags (np, (tp - np->target), ln);
-               }
-       }
-}
-
 static void ncr_setup_tags (ncb_p np, u_char tn, u_char ln)
 {
        tcb_p tp = &np->target[tn];
@@ -6671,10 +6652,17 @@ static void ncr_usercmd (ncb_p np)
 
        case UC_SETTAGS:
                for (t=0; t<MAX_TARGET; t++) {
+                       int ln;
                        if (!((np->user.target>>t)&1)) continue;
                        np->target[t].usrtags = np->user.data;
-                       ncr_setmaxtags (np, &np->target[t], np->user.data);
-               };
+                       for (ln = 0; ln < MAX_LUN; ln++) {
+                               lcb_p lp = np->target[t].lp[ln];
+                               if (!lp)
+                                       continue;
+                               lp->maxtags = lp->numtags = np->user.data;
+                               ncr_setup_tags (np, t, ln);
+                       }
+               };
                break;
 
        case UC_SETDEBUG:
@@ -7824,7 +7812,7 @@ void ncr_int_sir (ncb_p np)
 **     field of the controller's struct ncb.
 **
 **     Possible cases:            hs  sir   msg_in value  send   goto
-**     We try try to negotiate:
+**     We try to negotiate:
 **     -> target doesnt't msgin   NEG FAIL  noop   defa.  -      dispatch
 **     -> target rejected our msg NEG FAIL  reject defa.  -      dispatch
 **     -> target answered  (ok)   NEG SYNC  sdtr   set    -      clrack
@@ -8718,7 +8706,7 @@ static lcb_p ncr_setup_lcb (ncb_p np, u_char tn, u_char ln, u_char *inq_data)
        */
        if ((inq_byte7 ^ lp->inq_byte7) & INQ7_QUEUE) {
                lp->inq_byte7 = inq_byte7;
-               lp->numtags   = tp->usrtags;
+               lp->numtags   = lp->maxtags;
                ncr_setup_tags (np, tn, ln);
        }
 
@@ -9622,8 +9610,6 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
 #endif
        ncr_chip *chip;
 
-       printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
-               bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
        /*
         * Read info from the PCI config space.
         * pcibios_read_config_xxx() functions are assumed to be used for 
@@ -9650,6 +9636,11 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
                                        PCI_BASE_ADDRESS_1, &base);
        (void) pcibios_read_config_dword(bus, device_fn,
                                        PCI_BASE_ADDRESS_2, &base_2);
+
+       /* Handle 64bit base adresses for 53C896. */
+       if ((base & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
+               (void) pcibios_read_config_dword(bus, device_fn,
+                                                PCI_BASE_ADDRESS_3, &base_2);
        (void) pcibios_read_config_byte(bus, device_fn,
                                        PCI_INTERRUPT_LINE, &irq);
 #endif
@@ -9674,6 +9665,34 @@ static int ncr53c8xx_pci_init(Scsi_Host_Template *tpnt,
                chip->revision_id = revision;
                break;
        }
+
+#if defined(__i386__)
+       /*
+        *      Ignore Symbios chips controlled by SISL RAID controller.
+        */
+       if (chip && (base_2 & PCI_BASE_ADDRESS_MEM_MASK)) {
+               unsigned int ScriptsSize, MagicValue;
+               vm_offset_t ScriptsRAM;
+
+               if (chip->features & FE_RAM8K)
+                       ScriptsSize = 8192;
+               else
+                       ScriptsSize = 4096;
+
+               ScriptsRAM = remap_pci_mem(base_2 & PCI_BASE_ADDRESS_MEM_MASK,
+                                          ScriptsSize);
+               if (ScriptsRAM) {
+                       MagicValue = readl(ScriptsRAM + ScriptsSize - 16);
+                       unmap_pci_mem(ScriptsRAM, ScriptsSize);
+                       if (MagicValue == 0x52414944)
+                               return -1;
+               }
+       }
+#endif
+
+       printk(KERN_INFO "ncr53c8xx: at PCI bus %d, device %d, function %d\n",
+               bus, (int) (device_fn & 0xf8) >> 3, (int) device_fn & 7);
+
        if (!chip) {
                printk("ncr53c8xx: not initializing, device not supported\n");
                return -1;
@@ -10069,6 +10088,7 @@ static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_de
                ncb_p np;
                tcb_p tp;
                lcb_p lp;
+               int numtags;
 
                if (device->host != host)
                        continue;
@@ -10080,15 +10100,16 @@ static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_de
                /*
                **      Select queue depth from driver setup.
                **      Donnot use more than configured by user.
-               **      Use 2 for devices that donnot support tags.
                **      Use at least 2.
                **      Donnot use more than our maximum.
                */
-               device->queue_depth =
-                       device_queue_depth(np, device->id, device->lun);
-               if (device->queue_depth > tp->usrtags)
-                       device->queue_depth = tp->usrtags;
-               if (!device->tagged_supported || device->queue_depth < 2)
+               numtags = device_queue_depth(np, device->id, device->lun);
+               if (numtags > tp->usrtags)
+                       numtags = tp->usrtags;
+               if (!device->tagged_supported)
+                       numtags = 1;
+               device->queue_depth = numtags;
+               if (device->queue_depth < 2)
                        device->queue_depth = 2;
                if (device->queue_depth > SCSI_NCR_MAX_TAGS)
                        device->queue_depth = SCSI_NCR_MAX_TAGS;
@@ -10098,8 +10119,10 @@ static void ncr53c8xx_select_queue_depths(struct Scsi_Host *host, struct scsi_de
                **      we need to know this value in order not to 
                **      announce stupid things to user.
                */
-               if (lp)
+               if (lp) {
+                       lp->numtags = lp->maxtags = numtags;
                        lp->scdev_depth = device->queue_depth;
+               }
                ncr_setup_tags (np, device->id, device->lun);
 
 #ifdef DEBUG_NCR53C8XX
index 8c513279b7d79b3f9783f899485d50c135919812..a84f8d53aefef4fbb15cbdb04256ac453aff3028 100644 (file)
@@ -45,7 +45,7 @@
 /*
 **     Name and revision of the driver
 */
-#define SCSI_NCR_DRIVER_NAME           "ncr53c8xx - revision 3.1b"
+#define SCSI_NCR_DRIVER_NAME           "ncr53c8xx - revision 3.1d"
 
 /*
 **     Check supported Linux versions
@@ -424,6 +424,10 @@ typedef struct {
 #define FE_LDSTR       (1<<13)
 #define FE_RAM         (1<<14)
 #define FE_CLK80       (1<<15)
+#define FE_RAM8K       (1<<16)
+#define FE_64BIT       (1<<17)
+#define FE_IO256       (1<<18)
+#define FE_NOPM                (1<<19)
 #define FE_CACHE_SET   (FE_ERL|FE_CLSE|FE_WRIE|FE_ERMP)
 #define FE_SCSI_SET    (FE_WIDE|FE_ULTRA|FE_ULTRA2|FE_DBLR|FE_QUAD|F_CLK80)
 #define FE_SPECIAL_SET (FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM)
@@ -484,7 +488,8 @@ typedef struct {
  FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
  ,                                                                     \
  {PCI_DEVICE_ID_NCR_53C896, 0xff, "896",  7, 31, 7,                    \
- FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM}\
+ FE_WIDE|FE_ULTRA2|FE_QUAD|FE_CACHE_SET|FE_BOF|FE_DFS|FE_LDSTR|FE_PFEN|FE_RAM|\
+ FE_RAM8K|FE_64BIT|FE_IO256|FE_NOPM}\
 }
 
 /*
index 1ec38a9dcd3554ad28653063ce6ac5f330199e22..064785074f5152a33985d55d5755cc249c42a9de 100644 (file)
@@ -607,10 +607,9 @@ void scsi_old_done (Scsi_Cmnd * SCpnt)
        if ((++SCpnt->retries) < SCpnt->allowed)
        {
            if ((SCpnt->retries >= (SCpnt->allowed >> 1))
-               /* FIXME: last_reset == 0 is allowed
-                 *  && !(SCpnt->host->last_reset > 0 */ &&
-                    time_before(jiffies, SCpnt->host->last_reset
-                                 + MIN_RESET_PERIOD)
+               /* FIXME: last_reset == 0 is allowed */
+                && time_after(jiffies, SCpnt->host->last_reset
+                              + MIN_RESET_PERIOD)
                && !(SCpnt->flags & WAS_RESET))
            {
                printk("scsi%d channel %d : resetting for second half of retries.\n",
index a64e180cdbb9d76195a8ab02c2a21ebe60917f1c..34f82ff701db7b476c86bac2720d181c543bb579 100644 (file)
@@ -878,6 +878,7 @@ int sb_dsp_init(struct address_info *hw_config)
 
                        if(!sb16_set_dma_hw(devc)) {
                                free_irq(devc->irq, devc);
+                               release_region(hw_config->io_base, 16);
                                return 0;
                        }
 
index 12eeaf20451f7006525d4971ff08ffb63c35b86c..e3f1b1d8d3a1a99e4c960508ccf8d395a22ad705 100644 (file)
@@ -973,6 +973,11 @@ aty_init_cursor(struct fb_info_aty *fb))
 #endif
 #endif
 
+       if (! cursor->ram) {
+               kfree(cursor);
+               return NULL;
+       }
+
        if (curblink) {
                init_timer(cursor->timer);
                cursor->timer->expires = jiffies + (HZ / 50);
@@ -2917,6 +2922,11 @@ __initfunc(void atyfb_init(void))
            info->ati_regbase = (unsigned long)
                                ioremap(info->ati_regbase_phys, 0x1000);
 
+           if(!info->ati_regbase) {
+                   kfree(info);
+                   return;
+           }
+
            info->ati_regbase_phys += 0xc00;
            info->ati_regbase += 0xc00;
 
@@ -2939,6 +2949,11 @@ __initfunc(void atyfb_init(void))
            info->frame_buffer_phys = addr;
            info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
 
+           if(!info->frame_buffer) {
+                   kfree(info);
+                   return;
+           }
+
 #endif /* __sparc__ */
 
            if (!aty_init(info, "PCI")) {
@@ -3046,6 +3061,13 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
     info->ati_regbase_phys = 0x7ff000+addr;
     info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
                                                   0x1000);
+
+    if(! info->ati_regbase) {
+           printk("atyfb_init: ioremap() returned NULL\n");
+           kfree(info);
+           return;
+    }
+
     info->ati_regbase_phys += 0xc00;
     info->ati_regbase += 0xc00;
 
@@ -3067,6 +3089,12 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
     info->frame_buffer_phys = addr;
     info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
 
+    if(! info->frame_buffer) {
+           printk("atyfb_init: ioremap() returned NULL\n");
+           kfree(info);
+           return;
+    }
+
     if (!aty_init(info, dp->full_name)) {
        kfree(info);
        return;
index 74d62f54e1338a9e12592a7347d4a189ece2c538..b89906f189bf2922320a63b5b9cdf537e84ff5b5 100644 (file)
@@ -242,8 +242,6 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
 
        inode  = dentry->d_inode;
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode))
-               goto unlink_done;
        if (current->fsuid != inode->i_uid &&
            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto unlink_done;
index 4621e02f5a7c9f2a75e7c09d0ef8bad398907445..6ae3a91cd812d2d66bcb014f7620bcd423413e02 100644 (file)
@@ -661,7 +661,6 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        if (le32_to_cpu(de->inode) != inode->i_ino)
                goto end_rmdir;
 
-       down(&inode->i_sem);
        /*
         * Prune any child dentries so that this dentry becomes negative.
         */
@@ -686,7 +685,6 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
                retval = ext2_delete_entry (de, bh);
                dir->i_version = ++event;
        }
-       up(&inode->i_sem);
        if (retval)
                goto end_rmdir;
        mark_buffer_dirty(bh, 1);
@@ -733,8 +731,6 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
        DQUOT_INIT(inode);
 
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                goto end_unlink;
        if ((dir->i_mode & S_ISVTX) &&
index fdf699f9c4eaaef3397bc80b33fc1f1202e5915c..a7cb9a49e472b5b4c8d746fa20cc1ed1361ebb92 100644 (file)
@@ -490,8 +490,6 @@ repeat:
        inode = dentry->d_inode;
 
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (de->inode != inode->i_ino) {
                brelse(bh);
                current->counter = 0;
index b6843aaf69143385096da2878f44b4fb79bf27ca..b8348f13a648ceb5267fdaf24712f7e2a3ac7b01 100644 (file)
@@ -834,6 +834,37 @@ asmlinkage int sys_mkdir(const char * pathname, int mode)
        return error;
 }
 
+/*
+ * Whee.. Deadlock country. Happily there are only two VFS
+ * operations that do this..
+ */
+static inline void double_lock(struct dentry *d1, struct dentry *d2)
+{
+       struct semaphore *s1 = &d1->d_inode->i_sem;
+       struct semaphore *s2 = &d2->d_inode->i_sem;
+
+       if (s1 != s2) {
+               if ((unsigned long) s1 < (unsigned long) s2) {
+                       struct semaphore *tmp = s2;
+                       s2 = s1; s1 = tmp;
+               }
+               down(s1);
+       }
+       down(s2);
+}
+
+static inline void double_unlock(struct dentry *d1, struct dentry *d2)
+{
+       struct semaphore *s1 = &d1->d_inode->i_sem;
+       struct semaphore *s2 = &d2->d_inode->i_sem;
+
+       up(s1);
+       if (s1 != s2)
+               up(s2);
+       dput(d1);
+       dput(d2);
+}
+
 static inline int do_rmdir(const char * name)
 {
        int error;
@@ -845,13 +876,21 @@ static inline int do_rmdir(const char * name)
        if (IS_ERR(dentry))
                goto exit;
 
-       dir = lock_parent(dentry);
-       error = PTR_ERR(dir);
-       if (IS_ERR(dir))
-               goto exit_dput;
+       dir = dget(dentry->d_parent);
 
        error = -ENOENT;
        if (!dentry->d_inode)
+               goto exit;
+
+       /*
+        * The dentry->d_count stuff confuses d_delete() enough to
+        * not kill the inode from under us while it is locked. This
+        * wouldn't be needed, except the dentry semaphore is really
+        * in the inode, not in the dentry..
+        */
+       dentry->d_count++;
+       double_lock(dir, dentry);
+       if (dentry->d_parent != dir)
                goto exit_lock;
 
        error = -EROFS;
@@ -886,9 +925,8 @@ static inline int do_rmdir(const char * name)
        error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry);
 
 exit_lock:
-        unlock_dir(dir);
-exit_dput:
-       dput(dentry);
+       dentry->d_count--;
+       double_unlock(dentry, dir);
 exit:
        return error;
 }
@@ -943,13 +981,16 @@ static inline int do_unlink(const char * name)
                goto exit_lock;
 
        /*
+        * A directory can't be unlink'ed.
         * A file cannot be removed from an append-only directory.
         */
        error = -EPERM;
+       if (S_ISDIR(dentry->d_inode->i_mode))
+               goto exit_lock;
+
        if (IS_APPEND(dir->d_inode))
                goto exit_lock;
 
-       error = -EPERM;
        if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink)
                goto exit_lock;
 
@@ -1144,37 +1185,6 @@ asmlinkage int sys_link(const char * oldname, const char * newname)
        return error;
 }
 
-/*
- * Whee.. Deadlock country. Happily there is only one VFS
- * operation that does this..
- */
-static inline void double_lock(struct dentry *d1, struct dentry *d2)
-{
-       struct semaphore *s1 = &d1->d_inode->i_sem;
-       struct semaphore *s2 = &d2->d_inode->i_sem;
-
-       if (s1 != s2) {
-               if ((unsigned long) s1 < (unsigned long) s2) {
-                       struct semaphore *tmp = s2;
-                       s2 = s1; s1 = tmp;
-               }
-               down(s1);
-       }
-       down(s2);
-}
-
-static inline void double_unlock(struct dentry *d1, struct dentry *d2)
-{
-       struct semaphore *s1 = &d1->d_inode->i_sem;
-       struct semaphore *s2 = &d2->d_inode->i_sem;
-
-       up(s1);
-       if (s1 != s2)
-               up(s2);
-       dput(d1);
-       dput(d2);
-}
-
 static inline int do_rename(const char * oldname, const char * newname)
 {
        int error;
index 3f9c0ea005aee496b8774d6d652eef18c1c54d55..25caa03d32abc8482f94a07952ab858f2ecb9a01 100644 (file)
@@ -240,22 +240,21 @@ nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
        if (!fl->fl_owner || (fl->fl_flags & (FL_POSIX|FL_BROKEN)) != FL_POSIX)
                return -ENOLCK;
 
-       /* If unlocking a file region, flush dirty pages (unless we've
-        * been killed by a signal, that is). */
-       if (cmd == F_SETLK && fl->fl_type == F_UNLCK
-           && !signal_pending(current)) {
-               status = nfs_wb_area(inode, /* current->pid  ?*/
-                       fl->fl_start, fl->fl_end == NLM_OFFSET_MAX? 0 :
-                       fl->fl_end - fl->fl_start + 1);
-               if (status < 0)
-                       return status;
-       }
+       /*
+        * Flush all pending writes before doing anything
+        * with locks..
+        */
+       status = nfs_wb_all(inode);
+       if (status < 0)
+               return status;
 
        if ((status = nlmclnt_proc(inode, cmd, fl)) < 0)
                return status;
 
-       /* Here, we could turn off write-back of pages in the
-        * locked file region */
-
+       /*
+        * Make sure we re-validate anything we've got cached.
+        * This makes locking act as a cache coherency point.
+        */
+       NFS_CACHEINV(inode);
        return 0;
 }
index 82f213c55fc38b81084de2afd81c702f6c5e7c58..6ee83a82577ec3ea94a29bd80bb55342b324f370 100644 (file)
@@ -583,15 +583,6 @@ nfs_wb_pid(struct inode *inode, pid_t pid)
        NFS_WB(inode, req->wb_pid == pid);
 }
 
-/*
- * Write back everything in a specific area for locking purposes..
- */
-int
-nfs_wb_area(struct inode *inode, off_t offset, off_t len)
-{
-       NFS_WB(inode, 1);
-}
-
 /*
  * Write back and invalidate. Sometimes we can't leave the stuff
  * hanging if we can't write it out.
index d8a463befb66347bed703530fb16278a1a865da2..72d67a13ae5cf8b72ebe67a43135f64df1286c19 100644 (file)
@@ -1072,6 +1072,11 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
        if (IS_ERR(rdentry))
                goto out_nfserr;
 
+       /*
+        * FIXME!!
+        *
+        * This should do a double-lock on both rdentry and the parent
+        */
        err = fh_lock_parent(fhp, rdentry);
        if (err)
                goto out;
index 6f110d12667f43b77982cbe793609c887e2d23c1..05d8f9ea435031d8859d6c44ca0dc66bf3b2ef0f 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -797,11 +797,11 @@ int close_fp(struct file *filp, fl_owner_t id)
                printk("VFS: Close: file count is 0\n");
                return 0;
        }
-       if (dentry->d_inode)
-               locks_remove_posix(filp, id);
        retval = 0;
        if (filp->f_op && filp->f_op->flush)
                retval = filp->f_op->flush(filp);
+       if (dentry->d_inode)
+               locks_remove_posix(filp, id);
        fput(filp);
        return retval;
 }
index 99cbf05eb764f30be876a5f8ef458f8ba0fe3765..564fa66b28e18496e010ce6a2870924f7803d225 100644 (file)
@@ -245,9 +245,6 @@ int qnx4_unlink(struct inode *dir, struct dentry *dentry)
                goto end_unlink;
        }
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode)) {
-               goto end_unlink;
-       }
        if ((dir->i_mode & S_ISVTX) &&
            current->fsuid != inode->i_uid &&
            current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) {
index 626cc08a9e7a65f1d7e1ed4801cb3513d2f51fb9..fdae5c38c5a671360a0e0910c7ddf7023ad03f21 100644 (file)
@@ -476,8 +476,6 @@ repeat:
        inode = dentry->d_inode;
 
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (de->inode != inode->i_ino) {
                brelse(bh);
                current->counter = 0;
index bebfe1f66bee6ee318c62099eb23854294df2d34..130d53bb5c85d565e6ce0f2f6501eb502351615a 100644 (file)
@@ -701,7 +701,6 @@ int ufs_rmdir (struct inode * dir, struct dentry *dentry)
        if (SWAB32(de->d_ino) != inode->i_ino)
                goto end_rmdir;
 
-       down(&inode->i_sem);
        /*
         * Prune any child dentries so that this dentry becomes negative.
         */
@@ -727,7 +726,6 @@ int ufs_rmdir (struct inode * dir, struct dentry *dentry)
                retval = ufs_delete_entry (dir, de, bh);
                dir->i_version = ++event;
        }
-       up(&inode->i_sem);
        if (retval)
                goto end_rmdir;
        mark_buffer_dirty(bh, 1);
@@ -784,8 +782,6 @@ int ufs_unlink(struct inode * dir, struct dentry *dentry)
                inode->i_sb->dq_op->initialize (inode, -1);
 
        retval = -EPERM;
-       if (S_ISDIR(inode->i_mode))
-               goto end_unlink;
        if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
                goto end_unlink;
        if ((dir->i_mode & S_ISVTX) &&
index 0f7ba34c1ce210dd178d10a6773af57e124e5895..4535ec6abc429f2392289759b07036f0e86a77a2 100644 (file)
@@ -2,21 +2,19 @@ Changes by Matija Nalis (mnalis@jagor.srce.hr) on umsdos dentry fixing
 (started by Peter T. Waltenberg <peterw@karaka.chch.cri.nz>)
 (Final conversion to dentries Bill Hawes <whawes@star.net>)
 
----------- WARNING --------- WARNING --------- WARNING -----------
 There is no warning any more.
 Both read-only and read-write stuff is fixed, both in
 msdos-compatibile mode, and in umsdos EMD mode, and it seems stable.
-There are still few symlink/hardlink nuisances, but those are not fatal.
+There are still few hardlink nuisances, but those are not fatal.
 
-I'd call it wide beta, and ask for as many people as possible to
+I'd call it pre-release, and ask for as many people as possible to
 come and test it! See notes below for some more information, or if
 you are trying to use UMSDOS as root partition.
----------- WARNING --------- WARNING --------- WARNING -----------
 
 Legend: those lines marked with '+' on the beggining of line indicates it
 passed all of my tests, and performed perfect in all of them.
 
-Current status (981018) - UMSDOS dentry-Beta 0.83:
+Current status (981129) - UMSDOS dentry-pre 0.84:
 
 (1) pure MSDOS (no --linux-.--- EMD file):
 
@@ -51,13 +49,13 @@ READ:
 + resolve symlink              - works
 + dereference symlink          - works
 + dangling symlink             - works
-- hard links                   - seems to work mostly
++ hard links                   - works
 + special files (block/char devices, FIFOs, sockets...)        - works
-- various umsdos ioctls                - works
++ various umsdos ioctls                - works
 
 
 WRITE:
-- create symlink               - works mostly, but see WARNING below
++ create symlink               - works
 - create hardlink              - works, but see portability WARNING below
 + create file                  - works
 + create special file          - works
@@ -66,16 +64,16 @@ WRITE:
 + rename file (dif. dir)       - works
 - rename hardlink (same dir)   -
 - rename hardlink (dif. dir)   -
-- rename symlink (same dir)    - 
-- rename symlink (dif. dir)    - problems sometimes. see warning below.
++ rename symlink (same dir)    - works
++ rename symlink (dif. dir)    - works
 + rename dir (same dir)                - works
 + rename dir (dif. dir)                - works
 + delete file                  - works
 + notify_change (chown,perms)  - works
 + delete hardlink              - works
 + mkdir                                - works
-- rmdir                        - HMMM. see with clean --linux-.--- files...
-- umssyncing (many ioctls)     - works
++ rmdir                        - works
++ umssyncing (many ioctls)     - works
 
 
 - CVF-FAT stuff (compressed DOS filesystem) - there is some support from Frank
@@ -91,13 +89,6 @@ in filesystems that might be externally modified like umsdos. There is
 example is specs file about it. Specifically, moving directory which
 contains hardlinks will break them.
 
-Warning: moving symlinks around may break them until umount/remount.
-
-Warning: I seem to able to reproduce one problem with creting symlink after
-I rm -rf directory: it is manifested as symlink apperantly being regular
-file instead of symlink until next umount/mount pair. Tracking this one
-down...
-
 Note: (about pseudoroot) If you are currently trying to use UMSDOS as root
 partition (with linux installed in c:\linux) it will boot, but there are
 some problems. Volunteers ready to test pseudoroot are needed (preferably
@@ -105,7 +96,8 @@ ones with working backups or unimportant data). There are problems with
 different interpretation of hard links in normal in pseudo-root modes,
 resulting is 'silent delete' of them sometimes. Also, '/DOS' pseudo
 directory is only partially re-implemented and buggy. It works most of the
-time, though.
+time, though. Update: should work ok in 0.84, although it still does not
+work correctly in combination with initrd featere. Working on this!
 
 Warning: (about creating hardlinks in pseudoroot mode) - hardlinks created in
 pseudoroot mode are not compatibile with 'normal' hardlinks, and vice versa.
@@ -114,6 +106,8 @@ That is because harlink which is /foo in pseudoroot mode, becomes
 people either always use pseudoroot, or always use normal umsdos filesystem,
 this is no showstopper.
 
+Warning: (about hardlinks) - modifying hardlinks (esp. if there are in
+different directories) are currently somewhat broken, I'm working on it.
 
 ------------------------------------------------------------------------------
 
index ab983212e2a8f44780d1483959860f38de600124..41740fd425888512563d1155495386dafde7fe66 100644 (file)
@@ -66,10 +66,10 @@ void check_page_tables (void)
 void check_sb (struct super_block *sb, const char c)
 {
        if (sb) {
-               Printk ((" (has %c_sb=%d, %d)", 
-                       c, MAJOR (sb->s_dev), MINOR (sb->s_dev)));
+               printk (" (has %c_sb=%d, %d)", 
+                       c, MAJOR (sb->s_dev), MINOR (sb->s_dev));
        } else {
-               Printk ((" (%c_sb is NULL)", c));
+               printk (" (%c_sb is NULL)", c);
        }
 } 
 
@@ -81,35 +81,37 @@ extern struct inode_operations umsdos_rdir_inode_operations;
 void check_inode (struct inode *inode)
 {
        if (inode) {
-               Printk ((KERN_DEBUG "*   inode is %lu (i_count=%d)",
-                        inode->i_ino, inode->i_count));
+               printk (KERN_DEBUG "*   inode is %lu (i_count=%d)",
+                        inode->i_ino, inode->i_count);
                check_sb (inode->i_sb, 'i');
                
                if (inode->i_dentry.next) {     /* FIXME: does this work ? */
-                       Printk ((" (has i_dentry)"));
+                       printk (" (has i_dentry)");
                } else {
-                       Printk ((" (NO i_dentry)"));
+                       printk (" (NO i_dentry)");
                }
                
+               printk (" (i_patched=%d)", inode->u.umsdos_i.i_patched);
+               
                if (inode->i_op == NULL) {
-                       Printk ((" (i_op is NULL)\n"));
+                       printk (" (i_op is NULL)\n");
                } else if (inode->i_op == &umsdos_dir_inode_operations) {
-                       Printk ((" (i_op is umsdos_dir_inode_operations)\n"));
+                       printk (" (i_op is umsdos_dir_inode_operations)\n");
                } else if (inode->i_op == &umsdos_file_inode_operations) {
-                       Printk ((" (i_op is umsdos_file_inode_operations)\n"));
+                       printk (" (i_op is umsdos_file_inode_operations)\n");
                } else if (inode->i_op == &umsdos_file_inode_operations_no_bmap) {
-                       Printk ((" (i_op is umsdos_file_inode_operations_no_bmap)\n"));
+                       printk (" (i_op is umsdos_file_inode_operations_no_bmap)\n");
                } else if (inode->i_op == &umsdos_file_inode_operations_readpage) {
-                       Printk ((" (i_op is umsdos_file_inode_operations_readpage)\n"));
+                       printk (" (i_op is umsdos_file_inode_operations_readpage)\n");
                } else if (inode->i_op == &umsdos_rdir_inode_operations) {
-                       Printk ((" (i_op is umsdos_rdir_inode_operations)\n"));
+                       printk (" (i_op is umsdos_rdir_inode_operations)\n");
                } else if (inode->i_op == &umsdos_symlink_inode_operations) {
-                       Printk ((" (i_op is umsdos_symlink_inode_operations)\n"));
+                       printk (" (i_op is umsdos_symlink_inode_operations)\n");
                } else {
-                       Printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
+                       printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
                }
        } else {
-               Printk ((KERN_DEBUG "*   inode is NULL\n"));
+               printk (KERN_DEBUG "*   inode is NULL\n");
        }
 }
 
@@ -127,40 +129,40 @@ void checkd_inode (struct inode *inode)
                return;
        }
 
-       Printk ((KERN_DEBUG "checkd_inode:  inode %lu\n", inode->i_ino));
+       printk (KERN_DEBUG "checkd_inode:  inode %lu\n", inode->i_ino);
        cur = inode->i_dentry.next;
        while (count++ < 10) {
                PRINTK (("1..."));
                if (!cur) {
-                       Printk ((KERN_ERR "checkd_inode: *** NULL reached. exit.\n"));
+                       printk (KERN_ERR "checkd_inode: *** NULL reached. exit.\n");
                        return;
                }
                PRINTK (("2..."));
                ret = list_entry (cur, struct dentry, d_alias);
                PRINTK (("3..."));
                if (cur == cur->next) {
-                       Printk ((KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n"));
+                       printk (KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n");
                        return;
                }
                PRINTK (("4..."));
                if (!ret) {
-                       Printk ((KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n"));
+                       printk (KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n");
                        return;
                }
                PRINTK (("5... (ret=%p)...", ret));
                PRINTK (("5.1.. (ret->d_dname=%p)...", &(ret->d_name)));
                PRINTK (("5.1.1. (ret->d_dname.len=%d)...", (int) ret->d_name.len));
                PRINTK (("5.1.2. (ret->d_dname.name=%c)...", ret->d_name.name));
-               Printk ((KERN_DEBUG "checkd_inode:   i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name));
+               printk (KERN_DEBUG "checkd_inode:   i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name);
                PRINTK (("6..."));
                cur = cur->next;
                PRINTK (("7..."));
 #if 1
-               Printk ((KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n"));
+               printk (KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n");
                return;
 #endif         
        }
-       Printk ((KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n"));
+       printk (KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n");
        return;
 }
 
@@ -172,19 +174,19 @@ void checkd_inode (struct inode *inode)
 void check_dent_int (struct dentry *dentry, int parent)
 {
        if (parent) {
-               Printk ((KERN_DEBUG "*  parent(%d) dentry: %.*s\n", 
-                       parent, (int) dentry->d_name.len, dentry->d_name.name));
+               printk (KERN_DEBUG "*  parent(%d) dentry: %.*s\n", 
+                       parent, (int) dentry->d_name.len, dentry->d_name.name);
        } else {
-               Printk ((KERN_DEBUG "*  checking dentry: %.*s\n",
-                        (int) dentry->d_name.len, dentry->d_name.name));
+               printk (KERN_DEBUG "*  checking dentry: %.*s\n",
+                        (int) dentry->d_name.len, dentry->d_name.name);
        }
        check_inode (dentry->d_inode);
-       Printk ((KERN_DEBUG "*   d_count=%d", dentry->d_count));
+       printk (KERN_DEBUG "*   d_count=%d", dentry->d_count);
        check_sb (dentry->d_sb, 'd');
        if (dentry->d_op == NULL) {
-               Printk ((" (d_op is NULL)\n"));
+               printk (" (d_op is NULL)\n");
        } else {
-               Printk ((" (d_op is UNKNOWN: %p)\n", dentry->d_op));
+               printk (" (d_op is UNKNOWN: %p)\n", dentry->d_op);
        }
 }
 
@@ -196,35 +198,35 @@ void check_dent_int (struct dentry *dentry, int parent)
 void check_dentry_path (struct dentry *dentry, const char *desc)
 {
        int count=0;
-       Printk ((KERN_DEBUG "*** check_dentry_path: %.60s\n", desc));
+       printk (KERN_DEBUG "*** check_dentry_path: %.60s\n", desc);
 
        if (!dentry) {
-               Printk ((KERN_DEBUG "*** checking dentry... it is NULL !\n"));
+               printk (KERN_DEBUG "*** checking dentry... it is NULL !\n");
                return;
        }
        if (IS_ERR(dentry)) {
-               Printk ((KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n",
-                        PTR_ERR(dentry)));
+               printk (KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n",
+                        PTR_ERR(dentry));
                return;
        }
        
        while (dentry && count < 10) {
                check_dent_int (dentry, count++);
                if (dentry == dentry->d_parent) {
-                       Printk ((KERN_DEBUG "*** end checking dentry (root reached ok)\n"));
+                       printk (KERN_DEBUG "*** end checking dentry (root reached ok)\n");
                        break;
                }
                dentry = dentry->d_parent;
        }
 
        if (count >= 10) {      /* if infinite loop detected */
-               Printk ((KERN_ERR 
-                       "*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n"));
+               printk (KERN_ERR 
+                       "*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n");
        }
        
        if (!dentry) {
-               Printk ((KERN_ERR 
-                       "*** WARNING ! NULL dentry ! check_dentry_path aborted !\n"));
+               printk (KERN_ERR 
+                       "*** WARNING ! NULL dentry ! check_dentry_path aborted !\n");
        }
 }
 #else
index 1291163e9de794a9dd8fcb7c626ba25f1a2f8b3e..6ab276ac442697b41aa2e3bbb5cce69b5db0341a 100644 (file)
@@ -383,7 +383,6 @@ void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info)
        if (inode->u.umsdos_i.i_patched)
                goto out;
        inode->u.umsdos_i.i_patched = 1;
-
        if (S_ISREG (entry->mode))
                entry->mtime = inode->i_mtime;
        inode->i_mode = entry->mode;
index 4b8e1bfcc68c71d6516cb1dd22d0700c97e088c5..ef6e56dc3d7a23cee8c2ce040a32955501ffe6c8 100644 (file)
@@ -60,6 +60,7 @@ void UMSDOS_put_inode (struct inode *inode)
                        " Notify jacques@solucorp.qc.ca\n");
        }
 
+       inode->u.umsdos_i.i_patched = 0;
        fat_put_inode (inode);
 }
 
@@ -125,15 +126,6 @@ void umsdos_set_dirinfo_new (struct dentry *dentry, off_t f_pos)
 }
 
 
-/*
- * Tells if an Umsdos inode has been "patched" once.
- * Return != 0 if so.
- */
-int umsdos_isinit (struct inode *inode)
-{
-       return 0; /* inode->u.umsdos_i.i_emd_owner != 0; */
-}
-
 
 /*
  * Connect the proper tables in the inode and add some info.
@@ -200,7 +192,7 @@ dentry, f_pos));
  */
 void UMSDOS_read_inode (struct inode *inode)
 {
-       PRINTK ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",
+       Printk ((KERN_DEBUG "UMSDOS_read_inode %p ino = %lu ",
                inode, inode->i_ino));
        msdos_read_inode (inode);
 
@@ -235,8 +227,8 @@ int umsdos_notify_change_locked(struct dentry *dentry, struct iattr *attr)
        struct file filp;
        struct umsdos_dirent entry;
 
-Printk(("UMSDOS_notify_change: entering for %s/%s\n",
-dentry->d_parent->d_name.name, dentry->d_name.name));
+Printk(("UMSDOS_notify_change: entering for %s/%s (%d)\n",
+dentry->d_parent->d_name.name, dentry->d_name.name, inode->u.umsdos_i.i_patched));
 
        ret = inode_change_ok (inode, attr);
        if (ret) {
@@ -348,7 +340,8 @@ void UMSDOS_write_inode (struct inode *inode)
         * But it has the side effect to re"dirt" the inode.
         */
 /*      
- * internal_notify_change (inode, &newattrs);
+ * UMSDOS_notify_change (inode, &newattrs);
+
  * inode->i_state &= ~I_DIRTY; / * FIXME: this doesn't work.  We need to remove ourselves from list on dirty inodes. /mn/ */
 }
 
@@ -385,7 +378,7 @@ struct super_block *UMSDOS_read_super (struct super_block *sb, void *data,
        if (!res)
                goto out_fail;
 
-       printk (KERN_INFO "UMSDOS dentry-Beta 0.83 "
+       printk (KERN_INFO "UMSDOS dentry-pre 0.84 "
                "(compatibility level %d.%d, fast msdos)\n", 
                UMSDOS_VERSION, UMSDOS_RELEASE);
 
index b0163041eee301ddd672220f65acab449224cb0b..f7b8a8d077f1a73cbdcf9a55b186679d6340061d 100644 (file)
@@ -1020,11 +1020,6 @@ dentry->d_parent->d_name.name, dentry->d_name.name);
                goto out;
        }
 
-       /*
-        * Lock the directory, then check whether it's empty.
-        */
-       down(&dentry->d_inode->i_sem);
-
        /* check whether the EMD is empty */
        ret = -ENOTEMPTY;
        empty = umsdos_isempty (dentry);
@@ -1050,7 +1045,6 @@ demd->d_parent->d_name.name, demd->d_name.name, err);
                }
        } else if (empty == 2)
                ret = 0;
-       up(&dentry->d_inode->i_sem);
        if (ret)
                goto out;
 
index de0cfbeffdb6ef755362be30dc2b8bc8d5acaa6e..317d8ac2cfaa3b5dc61ddf43235ff12535154be3 100644 (file)
@@ -83,17 +83,17 @@ int umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo)
 {
        int ret;
 
-       /* N.B. this won't work ... lookups of `..' are done by VFS */
-#ifdef BROKEN_TO_BITS
-       if (pseudo_root && len == 2 && name[0] == '.' && name[1] == '.' &&
-           dir == saved_root->d_inode) {
-printk (KERN_WARNING "umsdos_rlookup_x: we are at pseudo-root thingy?\n");
-               pseudo_root->i_count++;
-               d_add(dentry, pseudo_root);
-               ret = 0;
+       if (saved_root && dir == saved_root->d_inode && !nopseudo &&
+           dentry->d_name.len == UMSDOS_PSDROOT_LEN &&
+           memcmp (dentry->d_name.name, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN) == 0) {
+               /* #Specification: pseudo root / DOS/linux
+                * Even in the real root directory (c:\), the directory
+                * /linux won't show
+                */
+                
+               ret = -ENOENT;
                goto out;
        }
-#endif
 
        ret = msdos_lookup (dir, dentry);
        if (ret) {
@@ -111,20 +111,6 @@ Printk ((KERN_DEBUG "umsdos_rlookup_x: patch_dentry_inode %s/%s\n",
 dentry->d_parent->d_name.name, dentry->d_name.name));
                umsdos_patch_dentry_inode(dentry, 0);
 
-               /* N.B. Won't work -- /linux dentry will already have
-                * an inode, so we'll never get called here.
-                */
-#ifdef BROKEN_TO_BITS
-               if (dentry->d_inode == pseudo_root && !nopseudo) {
-                       /* #Specification: pseudo root / DOS/linux
-                        * Even in the real root directory (c:\), the directory
-                        * /linux won't show
-                        */
-printk(KERN_WARNING "umsdos_rlookup_x: do the pseudo-thingy...\n");
-                       /* make the dentry negative */
-                       d_delete(dentry);
-               }
-#endif
        }
 out:
        /* always install our dentry ops ... */
@@ -180,7 +166,6 @@ static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
        if (ret != -ENOTEMPTY)
                goto out;
 
-       down(&dentry->d_inode->i_sem);
        empty = umsdos_isempty (dentry);
        if (empty == 1) {
                struct dentry *demd;
@@ -194,7 +179,6 @@ static int UMSDOS_rrmdir ( struct inode *dir, struct dentry *dentry)
                        dput(demd);
                }
        }
-       up(&dentry->d_inode->i_sem);
        if (ret)
                goto out;
 
index 17ed1200f8351cc9dd03a520eafee2bafc429f29..2cb1b891c0cfebf137d12b0e57287157317c1fcf 100644 (file)
@@ -36,9 +36,9 @@ asmlinkage void __down_failed(void /* special register calling convention */);
 asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
 asmlinkage void __up_wakeup(void /* special register calling convention */);
 
-extern void __down(struct semaphore * sem);
-extern int  __down_interruptible(struct semaphore * sem);
-extern void __up(struct semaphore * sem);
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
 
 extern spinlock_t semaphore_wake_lock;
 
index 86a5fb1217be69674ee7e4c534d7fdd20c9d0cf5..a478c0c66f038668840eb3245f489974025108bc 100644 (file)
@@ -77,6 +77,7 @@ struct apm_bios_struct {
 extern struct apm_bios_info    apm_bios_info;
 
 extern void            apm_bios_init(void);
+extern void            apm_setup(char *, int *);
 
 extern int             apm_register_callback(int (*callback)(apm_event_t));
 extern void            apm_unregister_callback(int (*callback)(apm_event_t));
index 5ac782d40d7a4e1c2adf2ab1ad24c73c7337e567..190202f0589911d5043f850d342c428509ff10b7 100644 (file)
@@ -2,9 +2,15 @@
 #define _LINUX_LINKAGE_H
 
 #ifdef __cplusplus
-#define asmlinkage extern "C"
+#define CPP_ASMLINKAGE extern "C"
 #else
-#define asmlinkage
+#define CPP_ASMLINKAGE
+#endif
+
+#if defined __i386__ && (__GNUC__ > 2 || __GNUC_MINOR__ > 7)
+#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
+#else
+#define asmlinkage CPP_ASMLINKAGE
 #endif
 
 #define SYMBOL_NAME_STR(X) #X
index b5b4e73931378795b94d13087de862d1543916d6..a60d29860a31eda9f564a02ba63343526fc1040d 100644 (file)
 #define LP_NOPA  0x0010
 #define LP_ERR   0x0020
 #define LP_ABORT 0x0040
-#ifdef LP_NEED_CAREFUL
-#define LP_CAREFUL 0x0080
-#endif
+#define LP_CAREFUL 0x0080 /* obsoleted -arca */
 #define LP_ABORTOPEN 0x0100
+#define        LP_TRUST_IRQ 0x0200
 
 /* timeout for each character.  This is relative to bus cycles -- it
  * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
 #define LP_INIT_CHAR 1000
 
 /* The parallel port specs apparently say that there needs to be
- * a .5usec wait before and after the strobe.  Since there are wildly
- * different computers running linux, I can't come up with a perfect
- * value so if 20 is not good for you use `tunelp /dev/lp? -w ?`.
- * You can also set it to 0 if your printer handle that.
+ * a .5usec wait before and after the strobe.
  */
 
-#define LP_INIT_WAIT 20
+#define LP_INIT_WAIT 1
 
 /* This is the amount of time that the driver waits for the printer to
  * catch up when the printer's buffer appears to be filled.  If you
                            or 0 for polling (no IRQ) */
 #define LPGETIRQ 0x0606  /* get the current IRQ number */
 #define LPWAIT   0x0608  /* corresponds to LP_INIT_WAIT */
-#ifdef LP_NEED_CAREFUL
+/* NOTE: LPCAREFUL is obsoleted and it' s always the default right now -arca */
 #define LPCAREFUL   0x0609  /* call with TRUE arg to require out-of-paper, off-
                            line, and error indicators good on all writes,
                            FALSE to ignore them.  Default is ignore. */
-#endif
 #define LPABORTOPEN 0x060a  /* call with TRUE arg to abort open() on error,
                            FALSE to ignore error.  Default is ignore.  */
 #define LPGETSTATUS 0x060b  /* return LP_S(minor) */
@@ -83,6 +78,7 @@
 #define LPGETSTATS  0x060d  /* get statistics (struct lp_stats) */
 #endif
 #define LPGETFLAGS  0x060e  /* get status flags */
+#define LPTRUSTIRQ  0x060f  /* set/unset the LP_TRUST_IRQ flag */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
@@ -96,7 +92,7 @@
 #define LP_TIME(minor) lp_table[(minor)].time          /* wait time */
 #define LP_WAIT(minor) lp_table[(minor)].wait          /* strobe wait */
 #define LP_IRQ(minor)  lp_table[(minor)].dev->port->irq /* interrupt # */
-                                                       /* 0 means polled */
+                                       /* PARPORT_IRQ_NONE means polled */
 #ifdef LP_STATS
 #define LP_STAT(minor) lp_table[(minor)].stats         /* statistics area */
 #endif
index 03e4c25e75f1024e75423ba011ac3fa3abade590..cc66279acce48cb41c03e6373b73f82ce2c7d400 100644 (file)
@@ -222,7 +222,6 @@ extern int  nfs_check_error(struct inode *);
 extern int  nfs_wb_all(struct inode *);
 extern int  nfs_wb_page(struct inode *, struct page *);
 extern int  nfs_wb_pid(struct inode *, pid_t);
-extern int  nfs_wb_area(struct inode *, off_t, off_t);
 
 /*
  * Invalidate write-backs, possibly trying to write them
index fac8a9397004259e9cadaf11f7691f310a31f485..ce29e37d5778d2d284fffef5c80d5fbb963e7513 100644 (file)
 #define PCI_DEVICE_ID_MADGE_C155S      0x1001
 
 #define PCI_VENDOR_ID_3COM             0x10b7
+#define PCI_DEVICE_ID_3COM_3C985       0x0001
 #define PCI_DEVICE_ID_3COM_3C339       0x3390
 #define PCI_DEVICE_ID_3COM_3C590       0x5900
 #define PCI_DEVICE_ID_3COM_3C595TX     0x5950
index 20b8f72f3f8780bfce31d88c4964bc6028f7d4c9..d4fcf03b8ce8681482c366c009fc72b884c3d457 100644 (file)
@@ -107,8 +107,8 @@ struct swap_list_t {
        int next;       /* swapfile to be used next */
 };
 extern struct swap_list_t swap_list;
-int sys_swapoff(const char *);
-int sys_swapon(const char *, int);
+asmlinkage int sys_swapoff(const char *);
+asmlinkage int sys_swapon(const char *, int);
 
 /*
  * vm_ops not present page codes for shared memory.
index 7a170c11540ef9fdaf0e933d0a571e5298568b42..14bdb829d4cd9ff82efcdac5fee1c69f14233337 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef LINUX_UMSDOS_FS_H
 #define LINUX_UMSDOS_FS_H
 
-/* #define UMSDOS_DEBUG 1 */
+
+#define UMS_DEBUG 1    /* define for check_* functions */
+/*#define UMSDOS_DEBUG 1*/
 #define UMSDOS_PARANOIA 1
 
 #define UMSDOS_VERSION 0
index 0da0ca36701d67ebfe9848fb75c2ff271a6d609a..1bf76e56051acb9cdf3b3a2b00f3f63f484f585e 100644 (file)
@@ -57,7 +57,6 @@ void UMSDOS_put_super (struct super_block *);
 
 void umsdos_setup_dir(struct dentry *);
 void umsdos_set_dirinfo_new(struct dentry *, off_t);
-int umsdos_isinit (struct inode *inode);
 void umsdos_patch_dentry_inode (struct dentry *, off_t);
 int umsdos_get_dirowner (struct inode *inode, struct inode **result);
 
index e41ba1fa0d327dcc96230b0ea42e0feae0ed365d..aaee2d2c74e64dd6f951d86ebe1b8c0d9626b8d1 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/blk.h>
+#include <linux/hdreg.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
 #  include <asm/mtrr.h>
 #endif
 
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
 /*
  * Versions of gcc older than that listed below may actually compile
  * and link okay, but the end product can have subtle run time bugs.
@@ -864,6 +869,9 @@ static struct kernel_param raw_params[] __initdata = {
 #endif
 #ifdef CONFIG_PARIDE_PG
         { "pg.", pg_setup },
+#endif
+#ifdef CONFIG_APM
+       { "apm=", apm_setup },
 #endif
        { 0, 0 }
 };
index 7a259cb5702d214533e166e40af68aaa1dec56b4..a625aaba38e72f435c2b59e28552f3e93d048030 100644 (file)
@@ -137,7 +137,7 @@ static inline struct task_struct ** find_empty_process(void)
 {
        struct task_struct **tslot = NULL;
 
-       if (!current->uid || (nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT))
+       if ((nr_tasks < NR_TASKS - MIN_TASKS_LEFT_FOR_ROOT) || !current->uid)
                tslot = get_free_taskslot();
        return tslot;
 }
index e2fd16518d4bea1cf9c8522d3fc3d9c052b47592..227bcd5a9ce77306b6f653224c0c43412577c5e6 100644 (file)
@@ -200,8 +200,8 @@ int shrink_mmap(int priority, int gfp_mask)
        struct page * page;
        int count_max, count_min;
 
-       count_max = (limit<<1) >> (priority>>1);
-       count_min = (limit<<1) >> (priority);
+       count_max = limit;
+       count_min = (limit<<2) >> (priority);
 
        page = mem_map + clock;
        do {
@@ -214,7 +214,15 @@ int shrink_mmap(int priority, int gfp_mask)
                if (shrink_one_page(page, gfp_mask))
                        return 1;
                count_max--;
-               if (page->inode || page->buffers)
+               /* 
+                * If the page we looked at was recyclable but we didn't
+                * reclaim it (presumably due to PG_referenced), don't
+                * count it as scanned.  This way, the more referenced
+                * page cache pages we encounter, the more rapidly we
+                * will age them. 
+                */
+               if (atomic_read(&page->count) != 1 ||
+                   (!page->inode && !page->buffers))
                        count_min--;
                page++;
                clock++;
index ff5e0f71dfcb89ab9ea457fe8de15cbf5993ddcd..1e2d8c36b279b9e3bbd94c334263126ee28992d0 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -62,13 +62,13 @@ swapstat_t swapstats = {0};
 
 buffer_mem_t buffer_mem = {
        5,      /* minimum percent buffer */
-       25,     /* borrow percent buffer */
+       10,     /* borrow percent buffer */
        60      /* maximum percent buffer */
 };
 
 buffer_mem_t page_cache = {
        5,      /* minimum percent page cache */
-       30,     /* borrow percent page cache */
+       15,     /* borrow percent page cache */
        75      /* maximum */
 };
 
index a93fdf6d2f5b3b4e21534ae8ab7dd9e068a63d2e..c5efa52a2050eee9a64d593f2080774a9146fa61 100644 (file)
@@ -431,7 +431,7 @@ static int do_try_to_free_page(int gfp_mask)
        kmem_cache_reap(gfp_mask);
 
        if (buffer_over_borrow() || pgcache_over_borrow())
-               shrink_mmap(i, gfp_mask);
+               state = 0;
 
        switch (state) {
                do {
index 06f4e308bc15199e362944d51fc9a6b95cc1deab..e0379e69b1c67b7aa1c05e54949c76c8fcbaa8ac 100644 (file)
@@ -31,21 +31,23 @@ if [ "$CONFIG_FIREWALL" = "y" ]; then
            define_bool CONFIG_NETLINK_DEV y
        fi
     fi
-    bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY
-    bool 'IP: always defragment' CONFIG_IP_ALWAYS_DEFRAG
+    bool 'IP: always defragment (required for masquerading)' CONFIG_IP_ALWAYS_DEFRAG
   fi
 fi
 if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
-  bool 'IP: masquerading' CONFIG_IP_MASQUERADE
-  if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
-    comment 'Protocol-specific masquerading support will be built as modules.'
-    bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
-    comment 'Protocol-specific masquerading support will be built as modules.'
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD 
-      if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
-        tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
-        tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+  if [ "$CONFIG_IP_ALWAYS_DEFRAG" != "n" ]; then
+    bool 'IP: transparent proxy support' CONFIG_IP_TRANSPARENT_PROXY
+    bool 'IP: masquerading' CONFIG_IP_MASQUERADE
+    if [ "$CONFIG_IP_MASQUERADE" != "n" ]; then
+      comment 'Protocol-specific masquerading support will be built as modules.'
+      bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
+      comment 'Protocol-specific masquerading support will be built as modules.'
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        bool 'IP: masquerading special modules support' CONFIG_IP_MASQUERADE_MOD 
+        if [ "$CONFIG_IP_MASQUERADE_MOD" = "y" ]; then
+          tristate 'IP: ipautofw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
+          tristate 'IP: ipportfw masq support (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPPORTFW
+       fi
       fi
     fi
   fi
index 75de39dec8922c5df232d46033b78c5c297ae81f..f486852d10753fed41b9cc7753eb06402015d5a7 100644 (file)
@@ -265,7 +265,7 @@ unsigned short tcp_good_socknum(void)
        struct tcp_bind_bucket *tb;
        int low = sysctl_local_port_range[0];
        int high = sysctl_local_port_range[1];
-       int remaining = high - low;
+       int remaining = high - low + 1;
        int rover;
 
        SOCKHASH_LOCK();