]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.100 2.1.100
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:26 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:26 +0000 (15:15 -0500)
180 files changed:
Documentation/Changes
arch/alpha/kernel/bios32.c
arch/alpha/kernel/ptrace.c
arch/arm/kernel/ioport.c
arch/arm/kernel/ptrace.c
arch/i386/kernel/entry.S
arch/i386/kernel/ioport.c
arch/i386/kernel/irq.c
arch/i386/kernel/ptrace.c
arch/i386/kernel/smp.c
arch/i386/kernel/trampoline.S
arch/i386/kernel/vm86.c
arch/m68k/kernel/ptrace.c
arch/m68k/kernel/sys_m68k.c
arch/mips/kernel/ptrace.c
arch/mips/kernel/sysirix.c
arch/mips/kernel/sysmips.c
arch/ppc/kernel/ptrace.c
arch/ppc/mm/init.c
arch/sparc/kernel/ptrace.c
arch/sparc64/kernel/psycho.c
arch/sparc64/kernel/ptrace.c
arch/sparc64/kernel/sys_sparc32.c
arch/sparc64/kernel/traps.c
arch/sparc64/solaris/fs.c
drivers/acorn/block/fd1772.c
drivers/acorn/block/mfmhd.c
drivers/ap1000/ddv.c
drivers/block/acsi.c
drivers/block/ali14xx.c
drivers/block/ataflop.c
drivers/block/dtc2278.c
drivers/block/floppy.c
drivers/block/hd.c
drivers/block/ht6560b.c
drivers/block/ide-cd.h
drivers/block/ide-disk.c
drivers/block/ide-dma.c
drivers/block/ide-floppy.c
drivers/block/ide-pci.c
drivers/block/ide-probe.c
drivers/block/ide-proc.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/loop.c
drivers/block/md.c
drivers/block/nbd.c
drivers/block/ns87415.c
drivers/block/opti621.c
drivers/block/paride/pd.c
drivers/block/paride/pf.c
drivers/block/pdc4030.c
drivers/block/ps2esdi.c
drivers/block/qd6580.c
drivers/block/rd.c
drivers/block/sl82c105.c
drivers/block/trm290.c
drivers/block/umc8672.c
drivers/block/xd.c
drivers/cdrom/sbpcd.c
drivers/char/apm_bios.c
drivers/char/bttv.c
drivers/char/console.c
drivers/char/esp.c
drivers/char/ftape/zftape/zftape-ctl.c
drivers/char/istallion.c
drivers/char/lp.c
drivers/char/nvram.c
drivers/char/random.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/rtc.c
drivers/char/serial.c
drivers/char/specialix.c
drivers/char/stallion.c
drivers/char/vt.c
drivers/isdn/avmb1/capi.c
drivers/macintosh/macserial.c
drivers/misc/TODO-parport
drivers/net/3c509.c
drivers/net/3c59x.c
drivers/net/de4x5.c
drivers/net/depca.c
drivers/net/dlci.c
drivers/net/eepro100.c
drivers/net/eql.c
drivers/net/ewrk3.c
drivers/net/ipddp.c
drivers/net/ppp.c
drivers/pci/proc.c
drivers/sbus/char/rtc.c
drivers/sbus/char/vfc_dev.c
drivers/sbus/char/zs.c
drivers/scsi/ide-scsi.c
drivers/scsi/ppa.c
drivers/scsi/scsi_ioctl.c
drivers/scsi/sd_ioctl.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
drivers/sgi/char/sgiserial.c
fs/affs/namei.c
fs/attr.c
fs/autofs/root.c
fs/buffer.c
fs/dquot.c
fs/exec.c
fs/ext2/acl.c
fs/ext2/balloc.c
fs/ext2/file.c
fs/ext2/inode.c
fs/ext2/ioctl.c
fs/ext2/namei.c
fs/minix/namei.c
fs/namei.c
fs/nfsd/nfsctl.c
fs/open.c
fs/proc/array.c
fs/proc/inode.c
fs/smbfs/proc.c
fs/super.c
fs/sysv/namei.c
fs/umsdos/namei.c
include/asm-alpha/ide.h
include/asm-alpha/mmu_context.h
include/asm-arm/ide.h
include/asm-arm/mmu_context.h
include/asm-i386/ide.h
include/asm-i386/mmu_context.h
include/asm-i386/spinlock.h
include/asm-i386/unistd.h
include/asm-m68k/ide.h
include/asm-m68k/mmu_context.h
include/asm-mips/ide.h
include/asm-mips/mmu_context.h
include/asm-ppc/ide.h
include/asm-ppc/mmu_context.h
include/asm-sparc/mmu_context.h
include/asm-sparc64/ide.h
include/asm-sparc64/mmu_context.h
include/linux/blk.h
include/linux/capability.h
include/linux/hdreg.h
include/linux/lp.h
include/linux/proc_fs.h
include/linux/sched.h
ipc/msg.c
ipc/sem.c
ipc/shm.c
ipc/util.c
kernel/Makefile
kernel/acct.c
kernel/capability.c [new file with mode: 0644]
kernel/fork.c
kernel/module.c
kernel/printk.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/time.c
mm/mlock.c
mm/page_alloc.c
mm/swapfile.c
net/appletalk/ddp.c
net/core/dev.c
net/core/scm.c
net/core/sock.c
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/ip_sockglue.c
net/ipv4/raw.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/route.c
net/packet/af_packet.c
net/rose/af_rose.c
net/wanrouter/wanmain.c
net/x25/af_x25.c

index 8bd1786ed79cf45a7efd6b2ac66472e84d5c2c4b..1da1ddf7ee8cb3a00f331d287fe22faf9c71f9cc 100644 (file)
@@ -33,7 +33,7 @@ http://cyberbuzz.gatech.edu/kaboom/linux/ as well.
    Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
 needs.
 
-Last updated: April 27, 1998
+Last updated: May 5, 1998
 Current Author: Chris Ricker (kaboom@gatech.edu).
 
 Current Minimal Requirements
@@ -60,7 +60,7 @@ running, the suggested command should tell you.
 - Bash                   1.14.7                  ; bash -version
 - Ncpfs                  2.1.1                   ; ncpmount -v
 - Pcmcia-cs              3.0.0
-- PPP                    2.3.3                   ; pppd -v
+- PPP                    2.3.5                   ; pppd -v
 
 Upgrade notes
 *************
@@ -127,6 +127,12 @@ Binutils
 to find out the proper way to upgrade it.  No, the instruction to "rm
 `which encaps`" is not a joke.
 
+The last public release of the binutils 2.8.x series is 2.8.1.0.23. 
+Binutils 2.8.1.0.25 to 2.9.1.0.2 are all very buggy; do not use them. 
+Binutils 2.9.1 (note the absence of a suffix) is all right, and binutils
+2.9.1.0.3 (and presumably later revisions) will probably work, too. 
+Stick with 2.8.1.0.23 to be safe. 
+
 Gnu C
 =====
 
@@ -423,14 +429,14 @@ ftp://ftp.gwdg.de/pub/linux/misc/ncpfs/ncpfs-2.1.1.tgz
 Pcmcia-cs
 =========
 
-The 3.0.0 release:
-ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs-3.0.0.tar.gz
+The May 4, 1998 release:
+ftp://hyper.stanford.edu/pub/pcmcia/NEW/pcmcia-cs.04-May-98.tar.gz
 
 PPP
 ===
 
-The 2.3.3 release:
-ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.3.tar.gz
+The 2.3.5 release:
+ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.5.tar.gz
 
 Other Info
 ==========
index 46880f11e6365c2ed12ee51038700ee0d1c7d27d..64c7442b645850c0f88ce52745a928da96cf810d 100644 (file)
@@ -2041,7 +2041,7 @@ asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
        unsigned int uint;
        long err = 0;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        lock_kernel();
@@ -2082,7 +2082,7 @@ asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
        unsigned int uint;
        long err = 0;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        lock_kernel();
index 38cb5e05d2439d1d00a66a47605115cf199940fa..c8b31623d25e6e0ce4878a911a7fb0e063ce98ed 100644 (file)
@@ -506,7 +506,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
                     (current->uid != child->uid) ||
                     (current->gid != child->egid) ||
                     (current->gid != child->sgid) ||
-                    (current->gid != child->gid)) && !suser())
+                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
                if (child->flags & PF_PTRACED)
index defa74335cce8629e984df4bc4890c6863e096d0..fe88df1731bc960329279839c0aa03e1f62aa331 100644 (file)
@@ -58,7 +58,7 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
        if (from + num > IO_BITMAP_SIZE*32)
                return -EINVAL;
 #endif
-       if (!suser())
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
 
 #ifdef IODEBUG
@@ -91,7 +91,7 @@ asmlinkage int sys_iopl(long ebx,long ecx,long edx,
 
        if (level > 3)
                return -EINVAL;
-       if (!suser())
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
        *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
        return 0;
index f95e8de7e0e010b741d4a04db162050a7d2a4383..9ca7bc964677f0d1896187cb1efef4a72c9b7cd4 100644 (file)
@@ -581,7 +581,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
                    (current->gid != child->sgid) ||
-                   (current->gid != child->gid)) && !suser())
+                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
                if (child->flags & PF_PTRACED)
index b6541005fbb51eda4b1e0a9888ccfb707aad987f..b3848c945b7a8721061fd13f491fb7cb6a3ab160 100644 (file)
@@ -544,7 +544,9 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_pwrite)
        .long SYMBOL_NAME(sys_chown)
        .long SYMBOL_NAME(sys_getcwd)
+       .long SYMBOL_NAME(sys_capget)
+       .long SYMBOL_NAME(sys_capset)           /* 185 */
        
-       .rept NR_syscalls-182
+       .rept NR_syscalls-184
                .long SYMBOL_NAME(sys_ni_syscall)
        .endr
index 19587312a0da7b90b9cb2d808e3961f7ed4545b0..2e3beb11b8eecc74ce01d9fe97c5fc19842f5e17 100644 (file)
@@ -58,7 +58,7 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
        if ((from + num <= from) || (from + num > IO_BITMAP_SIZE*32))
                return -EINVAL;
-       if (!suser())
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
        /*
         * If it's the first ioperm() call in this thread's lifetime, set the
@@ -94,7 +94,7 @@ asmlinkage int sys_iopl(unsigned long unused)
 
        if (level > 3)
                return -EINVAL;
-       if (!suser())
+       if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
        regs->eflags = (regs->eflags & 0xffffcfff) | (level << 12);
        return 0;
index 94736ed09e779088f37fbd7e2f5bd88a2593654b..fddc57c1feca4c9ae8d773a948befed6767806a3 100644 (file)
@@ -356,13 +356,14 @@ int get_irq_list(char *buf)
                        p += sprintf(p, "%10u ",
                                kstat.irqs[cpu_logical_map(j)][i]);
 #endif
-
                if (IO_APIC_IRQ(i)) {
                        p += sprintf(p, " IO-APIC");
+#ifdef __SMP__
                        if (irq_desc[i].handler == &ioapic_level_irq_type)
                                p += sprintf(p, "-level ");
                        else
                                p += sprintf(p, "-edge  ");
+#endif
                } else
                        p += sprintf(p, "  XT-PIC       ");
                p += sprintf(p, "  %s", action->name);
@@ -770,15 +771,25 @@ static void disable_edge_ioapic_irq(unsigned int irq)
 {
 }
 
+/*
+ * if we enable this, why does it cause a hang in the BusLogic
+ * driver, when level triggered PCI IRQs are used?
+ */
+#define NOT_BROKEN 0
+
 static void enable_level_ioapic_irq(unsigned int irq)
 {
+#if NOT_BROKEN
        enable_IO_APIC_irq(irq);
+#endif
        self_IPI(irq);
 }
 
 static void disable_level_ioapic_irq(unsigned int irq)
 {
+#if NOT_BROKEN
        disable_IO_APIC_irq(irq);
+#endif
 }
 
 /*
@@ -855,7 +866,9 @@ static void do_level_ioapic_IRQ (unsigned int irq, int cpu,
         * in the IO-APIC, then we 'early ACK' the IRQ, then we
         * handle it and enable the IRQ when finished.
         */
+#if NOT_BROKEN
        disable_IO_APIC_irq(irq);
+#endif
        ack_APIC_irq();
        desc->ipi = 0;
 
index d05b54b6314033e7b058065a134ce9bea330cc6c..294043faf33b886ffe6aaeedb18dfc4b5a399a44 100644 (file)
@@ -386,7 +386,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
                    (current->gid != child->sgid) ||
-                   (current->gid != child->gid)) && !suser())
+                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
                if (child->flags & PF_PTRACED)
index 2e862ca166ab4cd55e5aea94b146003a1d088f6d..ec7ee88c4cb445e5399c847a1adeeb2491cc7e75 100644 (file)
@@ -439,6 +439,8 @@ __initfunc(int smp_scan_config(unsigned long base, unsigned long length))
                                {
                                        unsigned long cfg;
 
+                                       /* local APIC has default address */
+                                       mp_lapic_addr = 0xFEE00000;
                                        /*
                                         *      We need to know what the local
                                         *      APIC id of the boot CPU is!
index 1f5303a9edcb36f09659efe063314bea4cad1c48..12c1dbe343f63fe730c537b190fcc8d20df80b91 100644 (file)
@@ -54,7 +54,7 @@ r_base = .
        lmsw    %ax             # into protected mode
        jmp     flush_instr
 flush_instr:
-       ljmp    $__KERNEL_CS, $0x00100000
+       ljmpl   $__KERNEL_CS, $0x00100000
                                # jump to startup_32
 
 idt_48:
index db7da10fc2c1f6ac538554ce0ac3bdcb062a773b..03bab3454d57959f98f89ead7f35286429a7ba18 100644 (file)
@@ -660,7 +660,7 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber)
                        int sig = irqnumber >> 8;
                        int irq = irqnumber & 255;
                        handle_irq_zombies();
-                       if (!suser()) return -EPERM;
+                       if (!capable(CAP_SYS_ADMIN)) return -EPERM;
                        if (!((1 << sig) & ALLOWED_SIGS)) return -EPERM;
                        if ( (irq<3) || (irq>15) ) return -EPERM;
                        if (vm86_irqs[irq].tsk) return -EPERM;
index 090f060ad50c4bdd128e39691d440840f4a4b4b5..4a2a95f4b03867af249d4b3449279f6f33f2d644 100644 (file)
@@ -340,7 +340,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
                    (current->gid != child->sgid) ||
-                   (current->gid != child->gid)) && !suser())
+                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
                if (child->flags & PF_PTRACED)
index b28a433742cc610a796c4c28a43ce0bea3989481..50d56413448e142b5c5a462b94ef0e1c8e33a36e 100644 (file)
@@ -548,7 +548,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
        if (scope == FLUSH_SCOPE_ALL) {
                /* Only the superuser may flush the whole cache. */
                ret = -EPERM;
-               if (!suser ())
+               if (!capable(CAP_SYS_ADMIN))
                        goto out;
        } else {
                /* Verify that the specified address region actually belongs to
index b5a5a442889c50856bd1de7a8ce1f21cbb1adde7..8d28a16aa4796d8932c5b1034792ba802c5b2ea2 100644 (file)
@@ -289,7 +289,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
                    (current->gid != child->sgid) ||
-                   (current->gid != child->gid)) && !suser()) {
+                   (current->gid != child->gid)) && 
+                   !capable(CAP_SYS_PTRACE)) {
                        res = -EPERM;
                        goto out;
                }
index c8f92bd8f33724a8c5b95ed8badbf97fe202ff24..72869c3690c6799d4e73cd934bf828ff198f12f3 100644 (file)
@@ -113,7 +113,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
                       current->comm, current->pid, (unsigned long) value);
                if(value > RLIM_INFINITY)
                        value = RLIM_INFINITY;
-               if(suser()) {
+               if(capable(CAP_SYS_ADMIN)) {
                        current->rlim[RLIMIT_STACK].rlim_max =
                                current->rlim[RLIMIT_STACK].rlim_cur = value;
                        error = value;
@@ -545,7 +545,7 @@ asmlinkage int irix_stime(int value)
        int ret;
 
        lock_kernel();
-       if(!suser()) {
+       if(!capable(CAP_SYS_TIME)) {
                ret = -EPERM;
                goto out;
        }
index 62f8687c07c16dba180ed1f20bbad56218b9da49..25e48cb04d5f64f0b3d644fc1f4fd9c44de87bad 100644 (file)
@@ -58,7 +58,7 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
        {
        case SETNAME:
                retval = -EPERM;
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        goto out;
 
                name = (char *) arg1;
index ce2f35058f1d65660c65c9c08d2561d90029caed..66dfb630fb7ce224478de5b06b62ea1a5bb31405 100644 (file)
@@ -331,7 +331,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
                    (current->uid != child->euid) ||
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
-                   (current->gid != child->gid)) && !suser())
+                   (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
                        goto out;
                /* the same process cannot be attached many times */
                if (child->flags & PF_PTRACED)
index 5967e29e64277f079720609b697b4f1f63f8e9e5..d13d8782130d2421954b623acad0da427ac12b5e 100644 (file)
@@ -1296,11 +1296,8 @@ local_flush_tlb_mm(struct mm_struct *mm)
 {
 #ifndef CONFIG_8xx
        mm->context = NO_CONTEXT;
-       if (mm == current->mm) {
-               get_mmu_context(current);
-               /* done by get_mmu_context() now -- Cort */
-               /*set_context(current->mm->context);*/
-       }
+       if (mm == current->mm)
+               activate_context(current);
 #else
        asm volatile ("tlbia" : : );
 #endif
index e50f308c72437ad5605375253056cb078e29960c..40e23fa0eec9c9074fb6d933d0c3f13487178c12 100644 (file)
@@ -539,7 +539,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                    (current->uid != child->euid) ||
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
-                   (current->gid != child->gid)) && !suser()) {
+                   (current->gid != child->gid)) && 
+                  !capable(CAP_SYS_PTRACE)) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
index 78a69e8df70e14210fd1c4c55e3baf93c9533fb2..bec1e9fef862b7f70d1e846f7725afa110aae3b4 100644 (file)
@@ -2323,7 +2323,7 @@ asmlinkage int sys_pciconfig_read(unsigned long bus,
        unsigned int uint;
        int err = 0;
 
-       if(!suser())
+       if(!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        lock_kernel();
@@ -2361,7 +2361,7 @@ asmlinkage int sys_pciconfig_write(unsigned long bus,
        unsigned int uint;
        int err = 0;
 
-       if(!suser())
+       if(!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        lock_kernel();
index 9174e7e452ca4e7c4bb214674437356f4eb9b3a2..5d3c6f46ab181fe1579c6a458b602162b73d7be7 100644 (file)
@@ -557,7 +557,8 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
                    (current->uid != child->euid) ||
                    (current->uid != child->uid) ||
                    (current->gid != child->egid) ||
-                   (current->gid != child->gid)) && !suser()) {
+                   (current->gid != child->gid)) && 
+                  !capable(CAP_SYS_PTRACE)) {
                        pt_error_return(regs, EPERM);
                        goto out;
                }
index 2844a4bf202ca908989f6d5e6d8f8bc5fadb258e..caad4273650b89d09cfb49865a79dae5a0b8922a 100644 (file)
@@ -1366,7 +1366,7 @@ asmlinkage int sys32_mount(u32 dev_name, u32 dir_name, u32 type, u32 new_flags,
        unsigned long type_page;
        int err, is_smb, is_ncp;
 
-       if(!suser())
+       if(!capable(CAP_SYS_ADMIN))
                return -EPERM;
        is_smb = is_ncp = 0;
        err = copy_mount_stuff_to_kernel((const void *)A(type), &type_page);
index b255c76239af02024b6ea61ae39382009107e389..069e908d0db6f8ee606e1a51828b83ed535c4f7a 100644 (file)
@@ -583,7 +583,7 @@ void cache_flush_trap(struct pt_regs *regs)
 
        regs->tpc = regs->tnpc;
        regs->tnpc = regs->tnpc + 4;
-       if (!suser()) return;
+       if (!capable(CAP_SYS_ADMIN)) return;
        size >>= PAGE_SHIFT;
        addr = PAGE_OFFSET - PAGE_SIZE;
        page = mem_map - 1;
index 39e69d2420b938a42ceab87cbd52f4f3cf1ee421..6df97c7c46f538e0e09bae442c8d752f44045bac 100644 (file)
@@ -464,7 +464,7 @@ asmlinkage int solaris_ulimit(int cmd, int val)
                val <<= 9;
                lock_kernel();
                if (val > current->rlim[RLIMIT_FSIZE].rlim_max) {
-                       if (!suser()) {
+                       if (!capable(CAP_SYS_RESOURCE)) {
                                unlock_kernel();
                                return -EPERM;
                        }
index 58ad6ce0d95e4b3743f5542535d7aa0f699f1470..765aeba677654b735115605b15cebef318842347 100644 (file)
@@ -1368,7 +1368,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
        case FDFLUSH:
                return invalidate_drive(drive);
        }
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (drive < 0 || drive > 3)
                return -EINVAL;
index 82c7e7bf585c5273f24d24c0b4d79d6dcb732c5c..40308c4e199931e90eb4098c1753e0a363683937 100644 (file)
@@ -1206,14 +1206,14 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
                return 0;
 
        case BLKFLSBUF:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                fsync_dev(dev);
                invalidate_buffers(dev);
                return 0;
 
        case BLKRASET:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                if (arg > 0xff)
                        return -EINVAL;
@@ -1227,7 +1227,7 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
                return put_user (mfm[minor].nr_sects, (long *)arg);
 
        case BLKFRASET:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                max_readahead[major][minor] = arg;
                return 0;
@@ -1239,7 +1239,7 @@ static int mfm_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long a
                return put_user(max_sectors[major][minor], (long *) arg);
 
        case BLKRRPART:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                return mfm_reread_partitions(dev);
 
index 2348e21d7646585fd431822a15d6b4f6951d9245..d58a5b9fb75f80b406849742011087229f549f66 100644 (file)
@@ -856,6 +856,8 @@ static int ddv_ioctl(struct inode *inode, struct file *file,
 
        case BLKRRPART:
                printk("\tBLKRRPART\n");
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EACCES;
                return ddv_revalidate(inode->i_rdev,&ddv_gendisk);
 
        case BLKGETSIZE:   /* Return device size */
index f04c0347feb0fc05ed22bbfd50e2dd23ce0f161f..432276973a2958dbc6b5a17d4df4147c5205e2a5 100644 (file)
@@ -1149,13 +1149,15 @@ static int acsi_ioctl( struct inode *inode, struct file *file,
                                (long *) arg);
                
          case BLKFLSBUF:
-               if(!suser())  return -EACCES;
+               if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                if(!inode->i_rdev) return -EINVAL;
                fsync_dev(inode->i_rdev);
                invalidate_buffers(inode->i_rdev);
                return 0;
 
          case BLKRRPART: /* Re-read partition tables */
+               if (!capable(CAP_SYS_ADMIN)) 
+                       return -EACCES;
                return revalidate_acsidisk(inode->i_rdev, 1);
          RO_IOCTLS(inode->i_rdev,arg);
          default:
index c0c7762d6c7395882773cc5c18cfaac3b17bd239..5d5ca66dc79dbcd3cdf179141e0d8eb4653d7592 100644 (file)
@@ -134,15 +134,15 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
 
        /* stuff timing parameters into controller registers */
        driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
-       save_flags(flags);
-       cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
        outb_p(regOn, basePort);
        outReg(param1, regTab[driveNum].reg1);
        outReg(param2, regTab[driveNum].reg2);
        outReg(param3, regTab[driveNum].reg3);
        outReg(param4, regTab[driveNum].reg4);
        outb_p(regOff, basePort);
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
 }
 
 /*
@@ -154,8 +154,8 @@ static int findPort (void)
        byte t;
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        for (i = 0; i < ALI_NUM_PORTS; ++i) {
                basePort = ports[i];
                regOff = inb(basePort);
@@ -166,7 +166,7 @@ static int findPort (void)
                                dataPort = basePort + 8;
                                t = inReg(0) & 0xf0;
                                outb_p(regOff, basePort);
-                               restore_flags(flags);
+                               __restore_flags(flags); /* local CPU only */
                                if (t != 0x50)
                                        return 0;
                                return 1;  /* success */
@@ -174,7 +174,7 @@ static int findPort (void)
                }
                outb_p(regOff, basePort);
        }
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
        return 0;
 }
 
@@ -186,15 +186,15 @@ static int initRegisters (void) {
        byte t;
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        outb_p(regOn, basePort);
        for (p = initData; p->reg != 0; ++p)
                outReg(p->data, p->reg);
        outb_p(0x01, regPort);
        t = inb(regPort) & 0x01;
        outb_p(regOff, basePort);
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
        return t;
 }
 
index 445e90fca7dcd0ccfc5f2b5066bc168525420c12..7a92f74a2c054a47fa5d77bd0405ef6147c1ab00 100644 (file)
@@ -1631,7 +1631,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
                        return -EFAULT;
                return 0;
        case BLKRASET:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                if (param > 0xff)
                        return -EINVAL;
@@ -1641,7 +1641,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp,
                return put_user(read_ahead[MAJOR(inode->i_rdev)],
                                (int *) param);
        case BLKFLSBUF:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EACCES;
                fsync_dev(inode->i_rdev);
                invalidate_buffers(inode->i_rdev);
index 63b9143b636ea153add435df169bf4754ee262be..b656a0bd27c32d0a66f8af16a2a16e9b26c3daee 100644 (file)
@@ -74,14 +74,14 @@ static void tune_dtc2278 (ide_drive_t *drive, byte pio)
        pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
 
        if (pio >= 3) {
-               save_flags(flags);
-               cli();
+               save_flags(flags);      /* all CPUs */
+               cli();                  /* all CPUs */
                /*
                 * This enables PIO mode4 (3?) on the first interface
                 */
                sub22(1,0xc3);
                sub22(0,0xa0);
-               restore_flags(flags);
+               restore_flags(flags);   /* all CPUs */
        } else {
                /* we don't know how to set it back again.. */
        }
@@ -97,8 +97,8 @@ void init_dtc2278 (void)
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        /*
         * This enables the second interface
         */
@@ -114,7 +114,7 @@ void init_dtc2278 (void)
        sub22(1,0xc3);
        sub22(0,0xa0);
 #endif
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
 
        ide_hwifs[0].serialized = 1;
        ide_hwifs[1].serialized = 1;
index 989da1497835f67493a76dc94e4885930364e9af..77f0b57651bcf4aee25cb65e85538f94cf0c05ec 100644 (file)
@@ -1825,7 +1825,6 @@ static void floppy_shutdown(void)
        if (!initialising)
                show_floppy();
        cancel_activity();
-       sti();
 
        floppy_enable_hlt();
        fd_disable_dma();
@@ -2876,7 +2875,6 @@ static void do_fd_request(void)
                printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
                return;
        }
-       sti();
        if (fdc_busy){
                /* fdc busy, this new request will be treated when the
                   current one is done */
@@ -3208,7 +3206,7 @@ static inline int set_geometry(unsigned int cmd, struct floppy_struct *g,
            (g->stretch&~(FD_STRETCH|FD_SWAPSIDES)) != 0)
                return -EINVAL;
        if (type){
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                LOCK_FDC(drive,1);
                for (cnt = 0; cnt < N_DRIVE; cnt++){
@@ -3373,7 +3371,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        return _COPYOUT(loc);
                }
                case BLKRASET:
-                       if(!suser()) return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if(param > 0xff) return -EINVAL;
                        read_ahead[MAJOR(inode->i_rdev)] = param;
                        return 0;
@@ -3381,7 +3379,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                        return put_user(read_ahead[MAJOR(inode->i_rdev)],
                                        (long *) param);
                case BLKFLSBUF:
-                       if(!suser()) return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN)) return -EACCES;
                        fsync_dev(inode->i_rdev);
                        invalidate_buffers(inode->i_rdev);
                        return 0;
index 558a1b2d2613a6150c86b6977fa3ee1f58aea0df..52bb33edeb6dbcdc92cd6084906d91a0827cb16c 100644 (file)
@@ -603,7 +603,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                        return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
                }
                case BLKRASET:
-                       if(!suser())  return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                        if(arg > 0xff) return -EINVAL;
                        read_ahead[MAJOR(inode->i_rdev)] = arg;
                        return 0;
@@ -616,12 +616,14 @@ static int hd_ioctl(struct inode * inode, struct file * file,
                        return put_user(hd[MINOR(inode->i_rdev)].nr_sects, 
                                        (long *) arg);
                case BLKFLSBUF:
-                       if(!suser())  return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                        fsync_dev(inode->i_rdev);
                        invalidate_buffers(inode->i_rdev);
                        return 0;
 
                case BLKRRPART: /* Re-read partition tables */
+                       if (!capable(CAP_SYS_ADMIN)) 
+                               return -EACCES;
                        return revalidate_hddisk(inode->i_rdev, 1);
 
                RO_IOCTLS(inode->i_rdev,arg);
index b739f39ee4d78c8dab796be8aabbb1d43d87eb13..6bf60e4ddc5b50b289f26989462ba34c54311d89 100644 (file)
@@ -133,8 +133,8 @@ static void ht6560b_selectproc (ide_drive_t *drive)
        if (select != current_select || timing != current_timing) {
                current_select = select;
                current_timing = timing;
-               save_flags (flags);
-               cli();
+               __save_flags (flags);   /* local CPU only */
+               __cli();                /* local CPU only */
                (void) inb(HT_SELECT_PORT);
                (void) inb(HT_SELECT_PORT);
                (void) inb(HT_SELECT_PORT);
@@ -150,7 +150,7 @@ static void ht6560b_selectproc (ide_drive_t *drive)
                  */
                 outb (timing, IDE_SELECT_REG);
                 (void) inb (IDE_STATUS_REG);
-               restore_flags (flags);
+               __restore_flags (flags);        /* local CPU only */
 #ifdef DEBUG
                printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, t, timing);
 #endif
index 661490027563dbd0c28e64d5571fe2a2c244bd77..785fbe1ed9eeab9a6ac369a395fb8d20ba3f6713 100644 (file)
@@ -415,7 +415,7 @@ struct cdrom_info {
 /* From Table 124 of the ATAPI 1.2 spec.
    Unchanged in Table 140 of the ATAPI 2.6 draft standard. */
 
-const char *sense_key_texts[16] = {
+const char * const sense_key_texts[16] = {
        "No sense data",
        "Recovered error",
        "Not ready",
@@ -436,9 +436,9 @@ const char *sense_key_texts[16] = {
 
 
 /* From Table 37 of the ATAPI 2.6 draft standard. */
-struct {
+const struct {
        unsigned short packet_command;
-       const char *text;
+       const char * const text;
 } packet_command_texts[] = {
        { TEST_UNIT_READY, "Test Unit Ready" },
        { REQUEST_SENSE, "Request Sense" },
@@ -471,9 +471,9 @@ struct {
 /* From Table 125 of the ATAPI 1.2 spec.,
    with additions from Tables 141 and 142 of the ATAPI 2.6 draft standard. */
 
-struct {
+const struct {
        unsigned short asc_ascq;
-       const char *text;
+       const char * const text;
 } sense_data_texts[] = {
        { 0x0000, "No additional sense information" },
 
index 5b46c8302c9da2c42b10eb7b234de4ee87267214..1ac07f698c4b878b2adcbf105d370f37369cc8f2 100644 (file)
  * Version 1.04                add /proc configurable settings and S.M.A.R.T support
  * Version 1.05                add capacity support for ATA3 >= 8GB
  * Version 1.06                get boot-up messages to show full cyl count
+ * Version 1.07                disable door-locking if it fails
  */
 
-#define IDEDISK_VERSION        "1.06"
+#define IDEDISK_VERSION        "1.07"
 
 #undef REALLY_SLOW_IO          /* most systems can safely undef this */
 
@@ -185,9 +186,7 @@ static void write_intr (ide_drive_t *drive)
                }
        } else
                error = 1;
-
 out:
-
        if (error)
                ide_error(drive, "write_intr", stat);
 }
@@ -258,9 +257,7 @@ static void multwrite_intr (ide_drive_t *drive)
                }
        } else
                error = 1;
-
 out:
-
        if (error)
                ide_error(drive, "multwrite_intr", stat);
 }
@@ -380,7 +377,7 @@ static void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long bl
                        return;
                }
                if (!drive->unmask)
-                       __cli();
+                       __cli();        /* local CPU only */
                if (drive->mult_count) {
                        HWGROUP(drive)->wrq = *rq; /* scratchpad */
                        ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
@@ -405,7 +402,8 @@ static int idedisk_open (struct inode *inode, struct file *filp, ide_drive_t *dr
                 * since the open() has already succeeded,
                 * and the door_lock is irrelevant at this point.
                 */
-               (void) ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL);
+               if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORLOCK, 0, 0, 0, NULL))
+                       drive->doorlocking = 0;
        }
        return 0;
 }
@@ -414,7 +412,8 @@ static void idedisk_release (struct inode *inode, struct file *filp, ide_drive_t
 {
        if (drive->removable && !drive->usage) {
                invalidate_buffers(inode->i_rdev);
-               (void) ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL);
+               if (drive->doorlocking && ide_wait_cmd(drive, WIN_DOORUNLOCK, 0, 0, 0, NULL))
+                       drive->doorlocking = 0;
        }
        MOD_DEC_USE_COUNT;
 }
@@ -587,8 +586,13 @@ static int set_multcount(ide_drive_t *drive, int arg)
 
 static int set_nowerr(ide_drive_t *drive, int arg)
 {
+       unsigned long flags;
+
+       if (ide_spin_wait_hwgroup("set_nowerr", drive, &flags))
+               return -EBUSY;
        drive->nowerr = arg;
        drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
+       spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
        return 0;
 }
 
@@ -658,14 +662,12 @@ static void idedisk_setup (ide_drive_t *drive)
 
        /* check for removable disks (eg. SYQUEST), ignore 'WD' drives */
        if (id->config & (1<<7)) {      /* removable disk ? */
-               if (id->model[0] != 'W' || id->model[1] != 'D')
+               if (id->model[0] != 'W' || id->model[1] != 'D') {
                        drive->removable = 1;
+                       drive->doorlocking = 1;
+               }
        }
 
-       /* SunDisk drives: treat as non-removable;   can mess up non-Sun systems!  FIXME */
-       if (id->model[0] == 'S' && id->model[1] == 'u')
-               drive->removable = 0;
-
        /* Extract geometry if we did not already have one for the drive */
        if (!drive->cyl || !drive->head || !drive->sect) {
                drive->cyl     = drive->bios_cyl  = id->cyls;
@@ -714,9 +716,10 @@ static void idedisk_setup (ide_drive_t *drive)
                if (drive->cyl > drive->bios_cyl)
                        drive->bios_cyl = drive->cyl;
        }
+#if 0  /* done instead for entire identify block in arch/ide.h stuff */
        /* fix byte-ordering of buffer size field */
        id->buf_size = le16_to_cpu(id->buf_size);
-
+#endif
        printk (KERN_INFO "%s: %.40s, %ldMB w/%dkB Cache, CHS=%d/%d/%d",
         drive->name, id->model, idedisk_capacity(drive)/2048L, id->buf_size/2,
         drive->bios_cyl, drive->bios_head, drive->bios_sect);
index 2cbed353922c0f0c8edc12624e83181d8b99702d..c314d1c829b6ee772550052204894bc230591bb7 100644 (file)
@@ -84,7 +84,7 @@
  */
 const char *good_dma_drives[] = {"Micropolis 2112A",
                                 "CONNER CTMA 4000",
-                                "ST34342A",
+                                "ST34342A",    /* for Sun Ultra */
                                 NULL};
 
 /*
@@ -128,7 +128,7 @@ void ide_dma_intr (ide_drive_t *drive)
                }
                printk("%s: dma_intr: bad DMA status\n", drive->name);
        }
-       sti();
+       ide__sti();     /* local CPU only */
        ide_error(drive, "dma_intr", stat);
 }
 
@@ -210,7 +210,7 @@ static int config_drive_for_dma (ide_drive_t *drive)
        struct hd_driveid *id = drive->id;
        ide_hwif_t *hwif = HWIF(drive);
 
-       if (id && (id->capability & 1) && !HWIF(drive)->no_autodma) {
+       if (id && (id->capability & 1) && !hwif->no_autodma) {
                /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
                if (id->field_valid & 4)        /* UltraDMA */
                        if  ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
@@ -250,6 +250,7 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
        ide_hwif_t *hwif = HWIF(drive);
        unsigned long dma_base = hwif->dma_base;
        unsigned int count, reading = 0;
+       byte dma_stat;
 
        switch (func) {
                case ide_dma_off:
@@ -267,22 +268,29 @@ int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                                return 1;       /* try PIO instead of DMA */
                        outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
                        outb(reading, dma_base);                        /* specify r/w */
-                       outb(inb(dma_base+2)|0x06, dma_base+2);         /* clear status bits */
+                       outb(inb(dma_base+2)|6, dma_base+2);            /* clear INTR & ERROR flags */
+                       drive->waiting_for_dma = 1;
                        if (drive->media != ide_disk)
                                return 0;
                        ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);/* issue cmd to drive */
                        OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
                case ide_dma_begin:
+                       /* Note that this is done *after* the cmd has
+                        * been issued to the drive, as per the BM-IDE spec.
+                        * The Promise Ultra33 doesn't work correctly when
+                        * we do this part before issuing the drive cmd.
+                        */
                        outb(inb(dma_base)|1, dma_base);                /* start DMA */
                        return 0;
                case ide_dma_end: /* returns 1 on error, 0 otherwise */
-               {
-                       byte dma_stat = inb(dma_base+2);
-                       int rc = (dma_stat & 7) != 4;
+                       drive->waiting_for_dma = 0;
+                       dma_stat = inb(dma_base+2);
                        outb(inb(dma_base)&~1, dma_base);               /* stop DMA */
                        outb(dma_stat|6, dma_base+2);   /* clear the INTR & ERROR bits */
-                       return rc;      /* verify good DMA status */
-               }
+                       return (dma_stat & 7) != 4;     /* verify good DMA status */
+               case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
+                       dma_stat = inb(dma_base+2);
+                       return (dma_stat & 4) == 4;     /* return 1 if INTR asserted */
                default:
                        printk("ide_dmaproc: unsupported func: %d\n", func);
                        return 1;
@@ -331,9 +339,10 @@ __initfunc(void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigne
 /*
  * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
  */
-__initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name))
+__initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name))
 {
-       unsigned long dma_base = 0;
+       unsigned long   dma_base = 0;
+       struct pci_dev  *dev = hwif->pci_dev;
 
        if (hwif->mate && hwif->mate->dma_base) {
                dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
index a4aa0b460e24d938554e541cdc5362c232fa1a6f..e59565e21f80fabaecc233e764720588385b5271 100644 (file)
@@ -713,7 +713,7 @@ static void idefloppy_pc_intr (ide_drive_t *drive)
 #endif /* IDEFLOPPY_DEBUG_LOG */
                clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
 
-               ide_sti();
+               ide__sti();     /* local CPU only */
 
                if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) {    /* Error detected */
 #if IDEFLOPPY_DEBUG_LOG
index 9dd5487f30c99dda631e445f5a14fc73cd1a1b00..811b7bed0fb1ed3cf89bb5434aa190fc61b1970c 100644 (file)
@@ -43,6 +43,7 @@
 #define DEVID_NS87415  ((ide_pci_devid_t){PCI_VENDOR_ID_NS,      PCI_DEVICE_ID_NS_87415})
 #define DEVID_HT6565   ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK,  PCI_DEVICE_ID_HOLTEK_6565})
 #define DEVID_AEC6210  ((ide_pci_devid_t){0x1191,                0x0005})
+#define DEVID_W82C105  ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
 
 #define IDE_IGNORE     ((void *)-1)
 
@@ -71,7 +72,18 @@ extern void ide_init_ns87415(ide_hwif_t *);
 extern void ide_init_cmd646(ide_hwif_t *);
 #define INIT_CMD646    &ide_init_cmd646
 #else
+#ifdef __sparc_v9__
 #define INIT_CMD646    IDE_IGNORE
+#else
+#define INIT_CMD646    NULL
+#endif
+#endif
+
+#ifdef CONFIG_BLK_DEV_SL82C105
+extern void ide_init_sl82c105(ide_hwif_t *);
+#define INIT_W82C105   &ide_init_sl82c105
+#else
+#define INIT_W82C105   IDE_IGNORE
 #endif
 
 #ifdef CONFIG_BLK_DEV_RZ1000
@@ -113,6 +125,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
        {DEVID_TRM290,  "TRM290",       INIT_TRM290,    {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
        {DEVID_NS87415, "NS87415",      INIT_NS87415,   {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
        {DEVID_AEC6210, "AEC6210",      NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
+       {DEVID_W82C105, "W82C105",      INIT_W82C105,   {{0x40,0x01,0x01}, {0x40,0x10,0x10}} },
        {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL,           {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }};
 
 /*
@@ -269,7 +282,7 @@ check_if_enabled:
                ide_pci_enablebit_t *e = &(d->enablebits[port]);
                if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
                        continue;       /* port not enabled */
-               ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK;
+               ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
                if (!ctl)
                        ctl = port ? 0x374 : 0x3f4;     /* use default value */
                base = dev->base_address[2*port] & ~7;
@@ -299,7 +312,7 @@ check_if_enabled:
                if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
                    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
                        unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
-                       unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name);
+                       unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
                        if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
                                /*
                                 * Set up BM-DMA capability (PnP BIOS should have done this)
index b2ea1bfd96f8199a355879d03b508e503bf865a1..7af146b283eec97205928126d4d9fd5e372887e1 100644 (file)
@@ -47,7 +47,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
 
        id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
        ide_input_data(drive, id, SECTOR_WORDS);        /* read 512 bytes of id info */
-       sti();
+       ide__sti();     /* local CPU only */
        ide_fix_driveid(id);
 
 #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -195,12 +195,12 @@ static int try_to_identify (ide_drive_t *drive, byte cmd)
        delay_50ms();           /* wait for IRQ and DRQ_STAT */
        if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
                unsigned long flags;
-               save_flags(flags);
-               cli();                  /* some systems need this */
+               __save_flags(flags);    /* local CPU only */
+               __cli();                /* local CPU only; some systems need this */
                do_identify(drive, cmd); /* drive returned ID */
                rc = 0;                 /* drive responded with ID */
                (void) GET_STAT();      /* clear drive IRQ */
-               restore_flags(flags);
+               __restore_flags(flags); /* local CPU only */
        } else
                rc = 2;                 /* drive refused ID */
        if (!HWIF(drive)->irq) {
@@ -398,8 +398,8 @@ static void probe_hwif (ide_hwif_t *hwif)
                return; 
        }
 
-       save_flags(flags);
-       sti();  /* needed for jiffies and irq probing */
+       __save_flags(flags);    /* local CPU only */
+       __sti();                /* local CPU only; needed for jiffies and irq probing */
        /*
         * Second drive should only exist if first drive was found,
         * but a lot of cdrom drives are configured as single slaves.
@@ -429,7 +429,7 @@ static void probe_hwif (ide_hwif_t *hwif)
                } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));
 
        }
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
        for (unit = 0; unit < MAX_DRIVES; ++unit) {
                ide_drive_t *drive = &hwif->drives[unit];
                if (drive->present) {
@@ -486,8 +486,8 @@ static int init_irq (ide_hwif_t *hwif)
        ide_hwgroup_t *hwgroup;
        ide_hwif_t *match = NULL;
 
-       save_flags(flags);
-       cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
 
        hwif->hwgroup = NULL;
 #if MAX_HWIFS > 1
@@ -499,7 +499,9 @@ static int init_irq (ide_hwif_t *hwif)
                if (h->hwgroup) {  /* scan only initialized hwif's */
                        if (hwif->irq == h->irq) {
                                hwif->sharing_irq = h->sharing_irq = 1;
-                               save_match(hwif, h, &match);
+                               if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
+                                       save_match(hwif, h, &match);
+                               }
                        }
                        if (hwif->serialized) {
                                if (hwif->mate && hwif->mate->irq == h->irq)
@@ -520,10 +522,15 @@ static int init_irq (ide_hwif_t *hwif)
        } else {
                hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL);
                memset(hwgroup, 0, sizeof(ide_hwgroup_t));
-               hwgroup->hwif    = hwif->next = hwif;
-               hwgroup->rq      = NULL;
-               hwgroup->handler = NULL;
-               hwgroup->drive   = NULL;
+               hwgroup->hwif     = hwif->next = hwif;
+               hwgroup->rq       = NULL;
+               hwgroup->handler  = NULL;
+               hwgroup->drive    = NULL;
+               hwgroup->busy     = 0;
+               hwgroup->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED;
+#if (DEBUG_SPINLOCK > 0)
+               printk("hwgroup(%s) spinlock is %p\n", hwif->name,  &hwgroup->spinlock);        /* FIXME */
+#endif
                init_timer(&hwgroup->timer);
                hwgroup->timer.function = &ide_timer_expiry;
                hwgroup->timer.data = (unsigned long) hwgroup;
@@ -533,10 +540,11 @@ static int init_irq (ide_hwif_t *hwif)
         * Allocate the irq, if not already obtained for another hwif
         */
        if (!match || match->irq != hwif->irq) {
-               if (ide_request_irq(hwif->irq, &ide_intr, SA_INTERRUPT, hwif->name, hwgroup)) {
+               int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
+               if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
                        if (!match)
                                kfree(hwgroup);
-                       restore_flags(flags);
+                       restore_flags(flags);   /* all CPUs */
                        return 1;
                }
        }
@@ -558,7 +566,7 @@ static int init_irq (ide_hwif_t *hwif)
                hwgroup->drive->next = drive;
        }
        hwgroup->hwif = HWIF(hwgroup->drive);
-       restore_flags(flags);   /* safe now that hwif->hwgroup is set up */
+       restore_flags(flags);   /* all CPUs; safe now that hwif->hwgroup is set up */
 
 #ifndef __mc68000__
        printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
@@ -685,13 +693,17 @@ static int hwif_init (ide_hwif_t *hwif)
                read_ahead[hwif->major] = 8;    /* (4kB) */
                hwif->present = 1;      /* success */
        }
+#if (DEBUG_SPINLOCK > 0)
+{
+       static int done = 0;
+       if (!done++)
+               printk("io_request_lock is %p\n", &io_request_lock);    /* FIXME */
+}
+#endif
        return hwif->present;
 }
 
-
-int ideprobe_init(void);
-
-
+int ideprobe_init (void);
 static ide_module_t ideprobe_module = {
        IDE_PROBE_MODULE,
        ideprobe_init,
index a86a51fdddb308393a1481659e9e51bb9a24e85e..26a56e7406904116f38cb9824264e59d077b50c9 100644 (file)
@@ -111,7 +111,7 @@ static int proc_ide_write_config
        unsigned long   startn = 0, n, flags;
        const char      *start = NULL, *msg = NULL;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        /*
         * Skip over leading whitespace
@@ -124,7 +124,7 @@ static int proc_ide_write_config
         * Do one full pass to verify all parameters,
         * then do another to actually write the regs.
         */
-       save_flags(flags);
+       save_flags(flags);      /* all CPUs */
        do {
                const char *p;
                if (for_real) {
@@ -133,14 +133,15 @@ static int proc_ide_write_config
                        ide_hwgroup_t *mategroup = NULL;
                        if (hwif->mate && hwif->mate->hwgroup)
                                mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
-                       cli();  /* ensure all writes are done together */
-                       while (mygroup->active || (mategroup && mategroup->active)) {
-                               restore_flags(flags);
+                       cli();  /* all CPUs; ensure all writes are done together */
+                       while (mygroup->busy || (mategroup && mategroup->busy)) {
+                               sti();  /* all CPUs */
                                if (0 < (signed long)(jiffies - timeout)) {
                                        printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name);
+                                       restore_flags(flags);   /* all CPUs */
                                        return -EBUSY;
                                }
-                               cli();
+                               cli();  /* all CPUs */
                        }
                }
                p = buffer;
@@ -155,7 +156,7 @@ static int proc_ide_write_config
                                                break;
                                case 'P':       is_pci = 1;
 #ifdef CONFIG_BLK_DEV_IDEPCI
-                                               if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
+                                               if (hwif->pci_dev && !IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
                                                        break;
 #endif /* CONFIG_BLK_DEV_IDEPCI */
                                                msg = "not a PCI device";
@@ -174,7 +175,7 @@ static int proc_ide_write_config
                                msg = "bad/missing register number";
                                goto parse_error;
                        }
-                       if (--n < 0 || *p++ != ':') {
+                       if (n-- == 0 || *p++ != ':') {
                                msg = "missing ':'";
                                goto parse_error;
                        }
@@ -223,7 +224,7 @@ static int proc_ide_write_config
                                                        break;
                                        }
                                        if (rc) {
-                                               restore_flags(flags);
+                                               restore_flags(flags);   /* all CPUs */
                                                printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
                                                        msg, dev->bus->number, dev->devfn, reg, val);
                                                printk("proc_ide_write_config: error %d\n", rc);
@@ -243,10 +244,10 @@ static int proc_ide_write_config
                        }
                }
        } while (!for_real++);
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
        return count;
 parse_error:
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
        printk("parse error\n");
        return xx_xx_parse_error(start, startn, msg);
 }
@@ -259,27 +260,25 @@ static int proc_ide_read_config
 
 #ifdef CONFIG_BLK_DEV_IDEPCI
        ide_hwif_t      *hwif = (ide_hwif_t *)data;
-       int             reg = 0;
+       struct pci_dev  *dev = hwif->pci_dev;
+       if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) {
+               int reg = 0;
 
-       struct pci_dev *dev = hwif->pci_dev;
-
-       out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
-               dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
-       do {
-               byte val;
-               int rc = pci_read_config_byte(dev, reg, &val);
-               if (rc) {
-                       printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
-                               dev->bus->number, dev->devfn, reg);
-                       printk("proc_ide_read_config: error %d\n", rc);
-                       return -EIO;
-                       out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
-               } else
-                       out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
-       } while (reg < 0x100);
-#else  /* CONFIG_BLK_DEV_IDEPCI */
-       out += sprintf(out, "(none)\n");
+               out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
+                       dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
+               do {
+                       byte val;
+                       int rc = pci_read_config_byte(dev, reg, &val);
+                       if (rc) {
+                               printk("proc_ide_read_config: error %d reading bus %02x dev %02x reg 0x%02x\n",
+                                       rc, dev->bus->number, dev->devfn, reg);
+                               out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
+                       } else
+                               out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
+               } while (reg < 0x100);
+       } else
 #endif /* CONFIG_BLK_DEV_IDEPCI */
+               out += sprintf(out, "(none)\n");
        len = out - page;
        PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
@@ -425,14 +424,13 @@ static int proc_ide_write_settings
        (struct file *file, const char *buffer, unsigned long count, void *data)
 {
        ide_drive_t     *drive = (ide_drive_t *) data;
-       ide_hwif_t      *hwif = HWIF(drive);
        char            name[MAX_LEN + 1];
        int             for_real = 0, len;
-       unsigned long   n, flags;
+       unsigned long   n;
        const char      *start = NULL;
        ide_settings_t  *setting;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        /*
         * Skip over leading whitespace
@@ -443,27 +441,10 @@ static int proc_ide_write_settings
        }
        /*
         * Do one full pass to verify all parameters,
-        * then do another to actually write the pci regs.
+        * then do another to actually write the new settings.
         */
-       save_flags(flags);
        do {
                const char *p;
-               if (for_real) {
-                       unsigned long timeout = jiffies + (3 * HZ);
-                       ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup);
-                       ide_hwgroup_t *mategroup = NULL;
-                       if (hwif->mate && hwif->mate->hwgroup)
-                               mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
-                       cli();  /* ensure all writes are done together */
-                       while (mygroup->active || (mategroup && mategroup->active)) {
-                               restore_flags(flags);
-                               if (0 < (signed long)(jiffies - timeout)) {
-                                       printk("/proc/ide/%s/settings: channel(s) busy, cannot write\n", drive->name);
-                                       return -EBUSY;
-                               }
-                               cli();
-                       }
-               }
                p = buffer;
                n = count;
                while (n > 0) {
@@ -508,10 +489,8 @@ static int proc_ide_write_settings
                                ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
                }
        } while (!for_real++);
-       restore_flags(flags);
        return count;
 parse_error:
-       restore_flags(flags);
        printk("proc_ide_write_settings(): parse error\n");
        return -EINVAL;
 }
@@ -573,7 +552,7 @@ static int proc_ide_write_driver
 {
        ide_drive_t     *drive = (ide_drive_t *) data;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (ide_replace_subdriver(drive, buffer))
                return -EINVAL;
index c4f5c6e2396dc693296beb65efed91bb80eb8afc..3b6e2790ff457b473dee352ee5a35979ad4b323c 100644 (file)
@@ -1432,8 +1432,8 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
 #if IDETAPE_DEBUG_LOG
        printk (KERN_INFO "Reached idetape_add_stage_tail\n");
 #endif /* IDETAPE_DEBUG_LOG */
-       save_flags (flags);
-       cli ();
+       save_flags (flags);     /* all CPUs (overkill?) */
+       cli();                  /* all CPUs (overkill?) */
        stage->next=NULL;
        if (tape->last_stage != NULL)
                tape->last_stage->next=stage;
@@ -1444,7 +1444,7 @@ static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
                tape->next_stage=tape->last_stage;
        tape->nr_stages++;
        tape->nr_pending_stages++;
-       restore_flags (flags);
+       restore_flags (flags);  /* all CPUs (overkill?) */
 }
 
 /*
@@ -1754,7 +1754,7 @@ static void idetape_pc_intr (ide_drive_t *drive)
 #endif /* IDETAPE_DEBUG_LOG */
                clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);
 
-               ide_sti();
+               ide__sti();     /* local CPU only */
 
                if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) {    /* Error detected */
 #if IDETAPE_DEBUG_LOG
@@ -2398,11 +2398,11 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
                 */
                return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
        }
-       save_flags (flags);
-       cli ();
+       save_flags (flags);     /* all CPUs (overkill?) */
+       cli();                  /* all CPUs (overkill?) */
        if (tape->active_stage == tape->first_stage)
                idetape_wait_for_request (tape->active_data_request);
-       restore_flags (flags);
+       restore_flags (flags);  /* all CPUs (overkill?) */
 
        rq_ptr = &tape->first_stage->rq;
        bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
@@ -2451,13 +2451,13 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
         *      Pay special attention to possible race conditions.
         */
        while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
-               save_flags (flags);
-               cli ();
+               save_flags (flags);     /* all CPUs (overkill?) */
+               cli();                  /* all CPUs (overkill?) */
                if (idetape_pipeline_active (tape)) {
                        idetape_wait_for_request (tape->active_data_request);
-                       restore_flags (flags);
+                       restore_flags (flags);  /* all CPUs (overkill?) */
                } else {
-                       restore_flags (flags);
+                       restore_flags (flags);  /* all CPUs (overkill?) */
                        idetape_insert_pipeline_into_queue (drive);
                        if (idetape_pipeline_active (tape))
                                continue;
@@ -2514,12 +2514,12 @@ static void idetape_discard_read_pipeline (ide_drive_t *drive)
        if (tape->first_stage == NULL)
                return;
                
-       save_flags (flags);
-       cli ();
+       save_flags (flags);     /* all CPUs (overkill?) */
+       cli();                  /* all CPUs (overkill?) */
        tape->next_stage = NULL;
        if (idetape_pipeline_active (tape))
                idetape_wait_for_request (tape->active_data_request);
-       restore_flags (flags);
+       restore_flags (flags);  /* all CPUs (overkill?) */
 
        while (tape->first_stage != NULL)
                idetape_remove_stage_head (drive);
@@ -2539,8 +2539,8 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
        if (!idetape_pipeline_active (tape))
                idetape_insert_pipeline_into_queue (drive);
 
-       save_flags (flags);
-       cli ();
+       save_flags (flags);     /* all CPUs (overkill?) */
+       cli();                  /* all CPUs (overkill?) */
        if (!idetape_pipeline_active (tape))
                goto abort;
 #if IDETAPE_DEBUG_BUGS
@@ -2550,7 +2550,7 @@ static void idetape_wait_for_pipeline (ide_drive_t *drive)
 #endif /* IDETAPE_DEBUG_BUGS */
        idetape_wait_for_request (&tape->last_stage->rq);
 abort:
-       restore_flags (flags);
+       restore_flags (flags);  /* all CPUs (overkill?) */
 }
 
 static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
@@ -2795,11 +2795,11 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
                         *      Wait until the first read-ahead request
                         *      is serviced.
                         */
-                       save_flags (flags);
-                       cli ();
+                       save_flags (flags);     /* all CPUs (overkill?) */
+                       cli();                  /* all CPUs (overkill?) */
                        if (tape->active_stage == tape->first_stage)
                                idetape_wait_for_request (tape->active_data_request);
-                       restore_flags (flags);
+                       restore_flags (flags);  /* all CPUs (overkill?) */
 
                        if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
                                count++;
@@ -3620,14 +3620,14 @@ static int idetape_cleanup (ide_drive_t *drive)
        int minor = tape->minor;
        unsigned long flags;
 
-       save_flags (flags);
-       cli ();
+       save_flags (flags);     /* all CPUs (overkill?) */
+       cli();                  /* all CPUs (overkill?) */
        if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) {
-               restore_flags(flags);
+               restore_flags(flags);   /* all CPUs (overkill?) */
                return 1;
        }
        idetape_chrdevs[minor].drive = NULL;
-       restore_flags (flags);
+       restore_flags (flags);  /* all CPUs (overkill?) */
        DRIVER(drive)->busy = 0;
        (void) ide_unregister_subdriver (drive);
        drive->driver_data = NULL;
index 111186eba2c471fad1e9896e09b76661bb55fbc7..191678d77467b2bfc2dca7cc5595535964de317f 100644 (file)
@@ -86,6 +86,9 @@
  * Version 6.12                integrate ioctl and proc interfaces
  *                     fix parsing of "idex=" command line parameter
  * Version 6.13                add support for ide4/ide5 courtesy rjones@orchestream.com
+ * Version 6.14                fixed IRQ sharing among PCI devices
+ * Version 6.15                added SMP awareness to IDE drivers
+ * Version 6.16                fixed various bugs; even more SMP friendly
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -155,13 +158,13 @@ static unsigned long read_timer(void)
        unsigned long t, flags;
        int i;
 
-       __save_flags(flags);
-       __cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        t = jiffies * 11932;
        outb_p(0, 0x43);
        i = inb_p(0x40);
        i |= inb(0x40) << 8;
-       __restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
        return (t - i);
 }
 #endif /* DISK_RECOVERY_TIME */
@@ -178,15 +181,11 @@ static inline void set_recovery_timer (ide_hwif_t *hwif)
  */
 static void init_hwif_data (unsigned int index)
 {
-       byte *p;
        unsigned int unit;
        ide_hwif_t *hwif = &ide_hwifs[index];
 
        /* bulk initialize hwif & drive info with zeros */
-       p = ((byte *) hwif) + sizeof(ide_hwif_t);
-       do {
-               *--p = 0;
-       } while (p > (byte *) hwif);
+       memset(hwif, 0, sizeof(ide_hwif_t));
 
        /* fill in any non-zero initial values */
        hwif->index     = index;
@@ -299,11 +298,11 @@ void ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 #if SUPPORT_VLB_SYNC
                if (io_32bit & 2) {
                        unsigned long flags;
-                       __save_flags(flags);
-                       __cli();
+                       __save_flags(flags);    /* local CPU only */
+                       __cli();                /* local CPU only */
                        do_vlb_sync(IDE_NSECTOR_REG);
                        insl(IDE_DATA_REG, buffer, wcount);
-                       __restore_flags(flags);
+                       __restore_flags(flags); /* local CPU only */
                } else
 #endif /* SUPPORT_VLB_SYNC */
                        insl(IDE_DATA_REG, buffer, wcount);
@@ -332,11 +331,11 @@ void ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
 #if SUPPORT_VLB_SYNC
                if (io_32bit & 2) {
                        unsigned long flags;
-                       __save_flags(flags);
-                       __cli();
+                       __save_flags(flags);    /* local CPU only */
+                       __cli();                /* local CPU only */
                        do_vlb_sync(IDE_NSECTOR_REG);
                        outsl(IDE_DATA_REG, buffer, wcount);
-                       __restore_flags(flags);
+                       __restore_flags(flags); /* local CPU only */
                } else
 #endif /* SUPPORT_VLB_SYNC */
                        outsl(IDE_DATA_REG, buffer, wcount);
@@ -391,6 +390,85 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
                outsw (IDE_DATA_REG, ((byte *)buffer) + (bytecount & ~0x03), 1);
 }
 
+/*
+ * Needed for PCI irq sharing
+ */
+static inline int drive_is_ready (ide_drive_t *drive)
+{
+       if (drive->waiting_for_dma)
+               return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
+#if 0
+       udelay(1);      /* need to guarantee 400ns since last command was issued */
+#endif
+       if (GET_STAT() & BUSY_STAT)
+               return 0;       /* drive busy:  definitely not interrupting */
+       return 1;               /* drive ready: *might* be interrupting */
+}
+
+#if !defined(__SMP__) && defined(DEBUG_SPINLOCKS) && (DEBUG_SPINLOCKS > 1)
+
+static const char *ide_lock_name(spinlock_t *spinlock)
+{
+       int index;
+
+       if (spinlock == &io_request_lock)
+               return "io_request_lock";
+       for (index = 0; index < MAX_HWIFS; index++) {
+               ide_hwif_t      *hwif    = &ide_hwifs[index];
+               ide_hwgroup_t   *hwgroup = hwif->hwgroup;
+               if (spinlock == &hwgroup->spinlock)
+                       return hwif->name;
+       }
+       return "?";
+}
+
+#define IDE_SPIN_LOCK_IRQ(msg,spinlock)                                \
+{                                                              \
+       static int __babble = 20;                               \
+       __cli();                                                        \
+       if ((spinlock)->lock && __babble) {                     \
+               __babble--;                                     \
+               printk("ide_lock: %s: already locked (%s)\n", msg, ide_lock_name(spinlock)); \
+       }                                                       \
+       /* spin_lock_irq(spinlock); */                          \
+       (spinlock)->lock = 1;                                   \
+}
+
+#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags)              \
+{                                                              \
+       __save_flags(flags);                                    \
+       IDE_SPIN_LOCK_IRQ(msg,spinlock);                        \
+}
+
+#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags)         \
+{                                                              \
+       static int __babble = 20;                               \
+       __cli();                                                        \
+       if (!((spinlock)->lock) && __babble) {                  \
+               __babble--;                                     \
+               printk("ide_unlock: %s: not locked (%s)\n", msg, ide_lock_name(spinlock)); \
+       }                                                       \
+       /* spin_unlock_irqrestore(msg,spinlock,flags); */       \
+       (spinlock)->lock = 0;                                   \
+       restore_flags(flags);                                   \
+}
+
+#define IDE_SPIN_UNLOCK(msg,spinlock)                          \
+{                                                              \
+       unsigned long __flags;                                  \
+       __save_flags(__flags);                                  \
+       IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,__flags);       \
+}
+
+#else  /* DEBUG_SPINLOCKS */
+
+#define IDE_SPIN_LOCK_IRQ(msg,spinlock)                        spin_lock_irq(spinlock)
+#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags)      spin_lock_irqsave(spinlock,flags)
+#define IDE_SPIN_UNLOCK(msg,spinlock)                  spin_unlock(spinlock)
+#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) spin_unlock_irqrestore(spinlock,flags)
+
+#endif /* DEBUG_SPINLOCKS */
+
 /*
  * This should get invoked any time we exit the driver to
  * wait for an interrupt response from a drive.  handler() points
@@ -400,7 +478,10 @@ void atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecoun
  */
 void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout)
 {
+       unsigned long flags;
        ide_hwgroup_t *hwgroup = HWGROUP(drive);
+
+       IDE_SPIN_LOCK_IRQSAVE("ide_set_handler", &hwgroup->spinlock, flags);
 #ifdef DEBUG
        if (hwgroup->handler != NULL) {
                printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
@@ -410,6 +491,7 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int t
        hwgroup->handler       = handler;
        hwgroup->timer.expires = jiffies + timeout;
        add_timer(&(hwgroup->timer));
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_set_handler", &hwgroup->spinlock, flags);
 }
 
 /*
@@ -558,8 +640,8 @@ static void do_reset1 (ide_drive_t *drive, int  do_not_try_atapi)
        ide_hwif_t *hwif = HWIF(drive);
        ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
-       __save_flags(flags);
-       __cli();                /* Why ? */
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
 
        /* For an ATAPI device, first try an ATAPI SRST. */
        if (drive->media != ide_disk && !do_not_try_atapi) {
@@ -569,7 +651,7 @@ static void do_reset1 (ide_drive_t *drive, int  do_not_try_atapi)
                OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
                hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
                ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
-               __restore_flags (flags);
+               __restore_flags (flags);        /* local CPU only */
                return;
        }
 
@@ -597,7 +679,7 @@ static void do_reset1 (ide_drive_t *drive, int  do_not_try_atapi)
        ide_set_handler (drive, &reset_pollfunc, HZ/20);
 #endif /* OK_TO_RESET_CONTROLLER */
 
-       __restore_flags (flags);
+       __restore_flags (flags);        /* local CPU only */
 }
 
 /*
@@ -625,15 +707,17 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
                        args[2] = IN_BYTE(IDE_NSECTOR_REG);
                }
        }
-       __save_flags(flags);
-       __cli();
+       IDE_SPIN_LOCK_IRQSAVE("ide_end_drive_cmd", &io_request_lock, flags);
        drive->queue = rq->next;
        blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
        HWGROUP(drive)->rq = NULL;
        rq->rq_status = RQ_INACTIVE;
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_end_drive_cmd", &io_request_lock, flags);
+       save_flags(flags);      /* all CPUs; overkill? */
+       cli();                  /* all CPUs; overkill? */
        if (rq->sem != NULL)
-               up(rq->sem);
-       __restore_flags(flags);
+               up(rq->sem);    /* inform originator that rq has been serviced */
+       restore_flags(flags);   /* all CPUs; overkill? */
 }
 
 /*
@@ -644,8 +728,8 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
        unsigned long flags;
        byte err = 0;
 
-       __save_flags (flags);
-       /* ide_sti(); HACK */
+       __save_flags (flags);   /* local CPU only */
+       ide__sti();             /* local CPU only */
        printk("%s: %s: status=0x%02x", drive->name, msg, stat);
 #if FANCY_STATUS_DUMPS
        printk(" { ");
@@ -698,7 +782,7 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
 #endif /* FANCY_STATUS_DUMPS */
                printk("\n");
        }
-       __restore_flags (flags);
+       __restore_flags (flags);        /* local CPU only */
        return err;
 }
 
@@ -732,7 +816,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
        byte err;
 
        err = ide_dump_status(drive, msg, stat);
-       if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
+       if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
                return;
        /* retry only "normal" I/O: */
        if (rq->cmd == IDE_DRIVE_CMD) {
@@ -784,7 +868,7 @@ void ide_error (ide_drive_t *drive, const char *msg, byte stat)
 void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
        ide_set_handler (drive, handler, WAIT_CMD);
-       OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
+       OUT_BYTE(drive->ctl,IDE_CONTROL_REG);   /* clear nIEN */
        OUT_BYTE(nsect,IDE_NSECTOR_REG);
        OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
@@ -799,7 +883,7 @@ static void drive_cmd_intr (ide_drive_t *drive)
        byte stat = GET_STAT();
        int retries = 10;
 
-       /* ide_sti(); HACK */
+       ide__sti();     /* local CPU only */
        if ((stat & DRQ_STAT) && args && args[3]) {
                byte io_32bit = drive->io_32bit;
                drive->io_32bit = 0;
@@ -857,17 +941,17 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
 
        udelay(1);      /* spec allows drive 400ns to assert "BUSY" */
        if ((stat = GET_STAT()) & BUSY_STAT) {
-               __save_flags(flags);
-               /* ide_sti(); HACK */
+               __save_flags(flags);    /* local CPU only */
+               ide__sti();             /* local CPU only */
                timeout += jiffies;
                while ((stat = GET_STAT()) & BUSY_STAT) {
                        if (0 < (signed long)(jiffies - timeout)) {
-                               __restore_flags(flags);
+                               __restore_flags(flags); /* local CPU only */
                                ide_error(drive, "status timeout", stat);
                                return 1;
                        }
                }
-               __restore_flags(flags);
+               __restore_flags(flags); /* local CPU only */
        }
        udelay(1);      /* allow status to settle, then read it again */
        if (OK_STAT((stat = GET_STAT()), good, bad))
@@ -909,17 +993,18 @@ static void execute_drive_cmd (ide_drive_t *drive, struct request *rq)
 }
 
 /*
- * do_request() initiates handling of a new I/O request
+ * start_request() initiates handling of a new I/O request
  */
-static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_drive_t *drive)
+static inline void start_request (ide_drive_t *drive)
 {
        unsigned long block, blockend;
        struct request *rq = drive->queue;
        unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
+       ide_hwif_t *hwif = HWIF(drive);
 
-       /* ide_sti(); HACK */
+       ide__sti();     /* local CPU only */
 #ifdef DEBUG
-       printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
+       printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
 #endif
        if (unit >= MAX_DRIVES) {
                printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
@@ -946,15 +1031,11 @@ static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_dri
 #if (DISK_RECOVERY_TIME > 0)
        while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
 #endif
-
-       hwgroup->hwif = hwif;
-       hwgroup->drive = drive;
        SELECT_DRIVE(hwif, drive);
        if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
                printk("%s: drive not ready for command\n", drive->name);
                return;
        }
-
        if (!drive->special.all) {
                if (rq->cmd == IDE_DRIVE_CMD) {
                        execute_drive_cmd(drive, rq);
@@ -973,7 +1054,7 @@ kill_rq:
        if (drive->driver != NULL)
                DRIVER(drive)->end_request(0, HWGROUP(drive));
        else
-               ide_end_request(0, hwgroup);
+               ide_end_request(0, HWGROUP(drive));
 }
 
 /*
@@ -1000,21 +1081,19 @@ repeat:
        best = NULL;
        drive = hwgroup->drive;
        do {
-               if (!drive->queue)
-                       continue;
-               if (drive->sleep && 0 < (signed long)(drive->sleep - jiffies))
-                       continue;
-               if (!best) {
-                       best = drive;
-                       continue;
+               if (drive->queue && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
+                       if (!best
+                        || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
+                        || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
+                       {
+                               struct blk_dev_struct *bdev = &blk_dev[HWIF(drive)->major];
+                               if (bdev->current_request != &bdev->plug)
+                                       best = drive;
+                       }
                }
-               if (drive->sleep && (!best->sleep || drive->sleep < best->sleep))
-                       best = drive;
-               if (!best->sleep && WAKEUP(drive) < WAKEUP(best))
-                       best = drive;
        } while ((drive = drive->next) != hwgroup->drive);
-       if (best != hwgroup->drive && best && best->service_time > WAIT_MIN_SLEEP && !best->sleep && best->nice1) {
-               long t = (signed) (WAKEUP(best) - jiffies);     /* BUGGY? */
+       if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
+               long t = (signed long)(WAKEUP(best) - jiffies);
                if (t >= WAIT_MIN_SLEEP) {
                        /*
                         * We *may* have some time to spare, but first let's see if
@@ -1022,9 +1101,10 @@ repeat:
                         */
                        drive = best->next;
                        do {
-                               if (drive->sleep)       /* this drive tried to be nice to us */
-                                       continue;
-                               if (WAKEUP(drive) > (jiffies - best->service_time) && WAKEUP(drive) < (jiffies + t)) {  /* BUGGY? */
+                               if (!drive->sleep
+                                && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
+                                && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
+                               {
                                        ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
                                        goto repeat;
                                }
@@ -1034,33 +1114,6 @@ repeat:
        return best;
 }
 
-static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
-{
-       ide_drive_t *drive = hwgroup->drive;
-       unsigned long sleep = 0;
-
-       hwgroup->rq = NULL;
-       do {
-               blk_dev[HWIF(drive)->major].current_request = NULL;
-               if (!drive->sleep)
-                       continue;
-               if (!sleep) {
-                       sleep = drive->sleep;
-                       continue;
-               }
-               if (drive->sleep < sleep)
-                       sleep = drive->sleep;
-       } while ((drive = drive->next) != hwgroup->drive);
-       if (sleep) {
-               if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) 
-                       sleep = jiffies + WAIT_MIN_SLEEP;
-               hwgroup->timer.expires = sleep;
-               add_timer(&hwgroup->timer);
-       } else  /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
-               ide_release_lock(&ide_lock);
-       hwgroup->active = 0;
-}
-
 /*
  * The driver enables interrupts as much as possible.  In order to do this,
  * (a) the device-interrupt is always masked before entry, and
@@ -1075,30 +1128,68 @@ static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
  * tolerance for latency during I/O.  For devices which don't suffer from
  * this problem (most don't), the unmask flag can be set using the "hdparm"
  * utility, to permit other interrupts during data/cmd transfers.
+ *
+ * Caller must have already acquired spinlock using *spinflags 
+ *
  */
-void ide_do_request (ide_hwgroup_t *hwgroup)
+static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq)
 {
-       __cli();        /* paranoia */
-       if (hwgroup->handler != NULL) {
-               printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name);
-               return;
-       }
-       do {
-               ide_drive_t *drive = choose_drive(hwgroup);
-               if (drive != NULL) {
-                       ide_hwif_t *hwif = HWIF(drive);
-                       if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif)
-                               OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
-                       drive->sleep = 0;
-                       blk_dev[hwif->major].current_request = hwgroup->rq = drive->queue;
-                       drive->service_start = jiffies;
-                       do_request(hwgroup, hwif, drive);
-                       __cli();
-               } else {
-                       ide_leave_hwgroup(hwgroup);     /* no work left for this hwgroup */
+       struct blk_dev_struct *bdev;
+       ide_drive_t     *drive;
+       ide_hwif_t      *hwif;
+       unsigned long   io_flags;
+
+       hwgroup->busy = 1;
+       while (hwgroup->handler == NULL) {
+               IDE_SPIN_LOCK_IRQSAVE("ide_do_request1", &io_request_lock, io_flags);
+               drive = choose_drive(hwgroup);
+               if (drive == NULL) {
+                       unsigned long sleep = 0;
+
+                       hwgroup->rq = NULL;
+                       drive = hwgroup->drive;
+                       do {
+                               bdev = &blk_dev[HWIF(drive)->major];
+                               if (bdev->current_request != &bdev->plug)       /* FIXME: this will do for now */
+                                       bdev->current_request = NULL;           /* (broken since patch-2.1.15) */
+                               if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
+                                       sleep = drive->sleep;
+                       } while ((drive = drive->next) != hwgroup->drive);
+                       IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request2", &io_request_lock, io_flags);
+                       if (sleep) {
+                               if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep)) 
+                                       sleep = jiffies + WAIT_MIN_SLEEP;
+                               hwgroup->timer.expires = sleep;
+                               add_timer(&hwgroup->timer);
+                       } else {
+                               /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
+                               ide_release_lock(&ide_lock);    /* for atari only */
+                       }
+                       hwgroup->busy = 0;
                        return;
                }
-       } while (hwgroup->handler == NULL);
+               hwif = HWIF(drive);
+               if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) /* set nIEN for previous hwif */
+                       OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
+               hwgroup->hwif = hwif;
+               hwgroup->drive = drive;
+               drive->sleep = 0;
+               drive->service_start = jiffies;
+
+               bdev = &blk_dev[hwif->major];
+               if (bdev->current_request == &bdev->plug)       /* FIXME: paranoia */
+                       printk("%s: Huh? nuking plugged queue\n", drive->name);
+               bdev->current_request = hwgroup->rq = drive->queue;
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request3", &io_request_lock, io_flags);
+
+               if (hwif->irq != masked_irq)
+                       disable_irq(hwif->irq);
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request4", &hwgroup->spinlock, *hwgroup_flags);
+               start_request(drive);
+               IDE_SPIN_LOCK_IRQSAVE("ide_do_request5", &hwgroup->spinlock, *hwgroup_flags);
+               if (hwif->irq != masked_irq)
+                       enable_irq(hwif->irq);
+       }
 }
 
 /*
@@ -1106,100 +1197,136 @@ void ide_do_request (ide_hwgroup_t *hwgroup)
  */
 struct request **ide_get_queue (kdev_t dev)
 {
-       struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
-       ide_hwif_t *hwif = bdev->data;
+       ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;
 
        return &hwif->drives[DEVICE_NR(dev) & 1].queue;
 }
 
 /*
- * do_hwgroup_request() invokes ide_do_request() after first masking
- * all possible interrupts for the current hwgroup.  This prevents race
- * conditions in the event that an unexpected interrupt occurs while
- * we are in the driver.
- *
- * Note that the io-request lock will guarantee that the driver never gets
- * re-entered even on another interrupt level, so we no longer need to
- * mask the irq's.
+ * do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy.
  */
-static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
+static void do_hwgroup_request (const char *msg, ide_hwgroup_t *hwgroup)
 {
-       if (hwgroup->handler == NULL) {
-               del_timer(&hwgroup->timer);
-               ide_get_lock(&ide_lock, ide_intr, hwgroup);
-               hwgroup->active = 1;
-               ide_do_request (hwgroup);
+       unsigned long flags;
+
+       IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, flags);
+       if (hwgroup->busy) {
+               IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+               return;
        }
+       del_timer(&hwgroup->timer);
+       ide_get_lock(&ide_lock, ide_intr, hwgroup);     /* for atari only */
+       ide_do_request(hwgroup, &flags, 0);
+       IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
+}
+
+/*
+ * As of linux-2.1.95, ll_rw_blk.c invokes our do_idex_request()
+ * functions with the io_request_spinlock already grabbed.
+ * Since we need to do our own spinlock's internally,
+ * on paths that don't necessarily originate through the
+ * do_idex_request() path.
+ *
+ * We have to undo the spinlock on entry, and restore it again on exit.
+ * Fortunately, this is mostly a nop for non-SMP kernels.
+ */
+static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup)
+{
+       IDE_SPIN_UNLOCK("unlock_do_hwgroup_request", &io_request_lock);
+       do_hwgroup_request ("from unlock_do_hwgroup_request", hwgroup);
+       IDE_SPIN_LOCK_IRQ("unlock_do_hwgroup_request", &io_request_lock);
 }
 
-void do_ide0_request (void)    /* invoked with __cli() */
+void do_ide0_request (void)
 {
-       do_hwgroup_request (ide_hwifs[0].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[0].hwgroup);
 }
 
 #if MAX_HWIFS > 1
-void do_ide1_request (void)    /* invoked with __cli() */
+void do_ide1_request (void)
 {
-       do_hwgroup_request (ide_hwifs[1].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[1].hwgroup);
 }
 #endif /* MAX_HWIFS > 1 */
 
 #if MAX_HWIFS > 2
-void do_ide2_request (void)    /* invoked with __cli() */
+void do_ide2_request (void)
 {
-       do_hwgroup_request (ide_hwifs[2].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[2].hwgroup);
 }
 #endif /* MAX_HWIFS > 2 */
 
 #if MAX_HWIFS > 3
-void do_ide3_request (void)    /* invoked with __cli() */
+void do_ide3_request (void)
 {
-       do_hwgroup_request (ide_hwifs[3].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[3].hwgroup);
 }
 #endif /* MAX_HWIFS > 3 */
 
 #if MAX_HWIFS > 4
-void do_ide4_request (void)    /* invoked with cli() */
+void do_ide4_request (void)
 {
-       do_hwgroup_request (ide_hwifs[4].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[4].hwgroup);
 }
 #endif /* MAX_HWIFS > 4 */
 
 #if MAX_HWIFS > 5
-void do_ide5_request (void)    /* invoked with cli() */
+void do_ide5_request (void)
 {
-       do_hwgroup_request (ide_hwifs[5].hwgroup);
+       unlock_do_hwgroup_request (ide_hwifs[5].hwgroup);
 }
 #endif /* MAX_HWIFS > 5 */
 
+static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
+{
+       unsigned long   flags;
+       ide_drive_t     *drive;
+
+       IDE_SPIN_LOCK_IRQSAVE("start_next_request", &hwgroup->spinlock, flags);
+       if (hwgroup->handler != NULL) {
+               IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+               return;
+       }
+       drive = hwgroup->drive;
+       set_recovery_timer(HWIF(drive));
+       drive->service_time = jiffies - drive->service_start;
+       ide_do_request(hwgroup, &flags, masked_irq);
+       IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
+}
+
 void ide_timer_expiry (unsigned long data)
 {
        ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
-       ide_drive_t   *drive   = hwgroup->drive;
+       ide_drive_t   *drive;
        ide_handler_t *handler;
        unsigned long flags;
 
-       __save_flags(flags);
-       __cli();
-
-       if ((handler = hwgroup->handler) != NULL) {
-               hwgroup->handler = NULL;
-               if (hwgroup->poll_timeout != 0) /* polling in progress? */
-                       handler(drive);
-               else {                          /* abort the operation */
-                       if (hwgroup->hwif->dmaproc)
-                               (void) hwgroup->hwif->dmaproc (ide_dma_end, drive);
-                       ide_error(drive, "irq timeout", GET_STAT());
-               }
-               __cli();
-               if (hwgroup->handler == NULL) {
-                       set_recovery_timer(HWIF(drive));
-                       drive->service_time = jiffies - drive->service_start;
-                       do_hwgroup_request (hwgroup);
+       IDE_SPIN_LOCK_IRQSAVE("ide_timer_expiry1", &hwgroup->spinlock, flags);
+       drive = hwgroup->drive;
+       if ((handler = hwgroup->handler) == NULL) {
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry2", &hwgroup->spinlock, flags);
+               do_hwgroup_request("timer do_hwgroup_request", hwgroup);
+               return;
+       }
+       hwgroup->busy = 1;      /* should already be "1" */
+       hwgroup->handler = NULL;
+       if (hwgroup->poll_timeout != 0) {       /* polling in progress? */
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry3", &hwgroup->spinlock, flags);
+               handler(drive);
+       } else if (drive_is_ready(drive)) {
+               printk("%s: lost interrupt\n", drive->name);
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry4", &hwgroup->spinlock, flags);
+               handler(drive);
+       } else {
+               if (drive->waiting_for_dma) {
+                       (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
+                       printk("%s: timeout waiting for DMA\n", drive->name);
                }
-       } else
-               do_hwgroup_request (hwgroup);
-       __restore_flags(flags);
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry5", &hwgroup->spinlock, flags);
+               ide_error(drive, "irq timeout", GET_STAT());
+       }
+       del_timer(&hwgroup->timer);
+       start_next_request(hwgroup, 0);
 }
 
 /*
@@ -1238,75 +1365,78 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
                        stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
                        if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
                                /* Try to not flood the console with msgs */
-                               static unsigned long last_msgtime = 0;
+                               static unsigned long last_msgtime = 0, count = 0;
+                               ++count;
                                if (0 < (signed long)(jiffies - (last_msgtime + HZ))) {
                                        last_msgtime = jiffies;
-                                       printk("%s%s: unexpected interrupt, status=0x%02x\n",
-                                        hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat);
+                                       printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n",
+                                        hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
                                }
                        }
                }
        } while ((hwif = hwif->next) != hwgroup->hwif);
 }
-
-#ifdef __sparc_v9__
-#define IDE_IRQ_EQUAL(irq1, irq2)      (1)
-#else
-#define IDE_IRQ_EQUAL(irq1, irq2)      ((irq1) == (irq2))
-#endif
-
-static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
-{
-       ide_hwgroup_t *hwgroup = dev_id;
-       ide_hwif_t *hwif = hwgroup->hwif;
-       ide_handler_t *handler;
-
-       if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
-               return;
-
-       if (IDE_IRQ_EQUAL(irq, hwif->irq)
-           && (handler = hwgroup->handler) != NULL) {
-               ide_drive_t *drive = hwgroup->drive;
-#if 1  /* temporary, remove later -- FIXME */
-               {
-                       struct request *rq = hwgroup->rq;
-                       if (rq != NULL
-                           &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
-                           || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
-                       {
-                               printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n");
-                               return;
-                       }
-               }
-#endif /* temporary */
-               hwgroup->handler = NULL;
-               del_timer(&(hwgroup->timer));
-               /* if (drive->unmask)
-                       ide_sti(); HACK */
-               handler(drive);
-               /* this is necessary, as next rq may be different irq */
-               if (hwgroup->handler == NULL) {
-                       set_recovery_timer(HWIF(drive));
-                       drive->service_time = jiffies - drive->service_start;
-                       ide_do_request(hwgroup);
-               }
-       } else {
-               unexpected_intr(irq, hwgroup);
-       }
-       __cli();
-       hwif = hwgroup->hwif;
-}
-
 /*
  * entry point for all interrupts, caller does __cli() for us
  */
 void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
 {
        unsigned long flags;
+       ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
+       ide_hwif_t *hwif;
+       ide_drive_t *drive;
+       ide_handler_t *handler;
 
-       spin_lock_irqsave(&io_request_lock, flags);
-       do_ide_intr(irq, dev_id, regs);
-       spin_unlock_irqrestore(&io_request_lock, flags);
+       __cli();        /* local CPU only */
+       IDE_SPIN_LOCK_IRQSAVE("ide_intr1", &hwgroup->spinlock, flags);
+       hwif = hwgroup->hwif;
+       if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
+               /*
+                * Not expecting an interrupt from this drive.
+                * That means this could be:
+                *      (1) an interrupt from another PCI device
+                *      sharing the same PCI INT# as us.
+                * or   (2) a drive just entered sleep or standby mode,
+                *      and is interrupting to let us know.
+                * or   (3) a spurious interrupt of unknown origin.
+                *
+                * For PCI, we cannot tell the difference,
+                * so in that case we just ignore it and hope it goes away.
+                */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+               if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
+#endif /* CONFIG_BLK_DEV_IDEPCI */
+               {
+                       /*
+                        * Probably not a shared PCI interrupt,
+                        * so we can safely try to do something about it:
+                        */
+                       (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
+                       unexpected_intr(irq, hwgroup);
+               }
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr2", &hwgroup->spinlock, flags);
+               return;
+       }
+       drive = hwgroup->drive;
+       if (!drive || !drive_is_ready(drive)) {
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr3", &hwgroup->spinlock, flags);
+               return;
+       }
+       hwgroup->handler = NULL;
+       (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
+       del_timer(&(hwgroup->timer));
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr4", &hwgroup->spinlock, flags);
+       if (drive->unmask)
+               ide__sti();     /* local CPU only */
+       handler(drive);         /* service this interrupt, may set handler for next interrupt */
+       /*
+        * Note that handler() may have set things up for another
+        * interrupt to occur soon, but it cannot happen until
+        * we exit from this routine, because it will be the
+        * same irq as is currently being serviced here,
+        * and Linux won't allow another (on any CPU) until we return.
+        */
+       start_next_request(hwgroup, hwif->irq);
 }
 
 /*
@@ -1390,10 +1520,8 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
        if (action == ide_wait)
                rq->sem = &sem;
 
-       __save_flags(flags);
-       __cli();
+       IDE_SPIN_LOCK_IRQSAVE("ide_do_drive_cmd", &io_request_lock, flags);
        cur_rq = drive->queue;
-
        if (cur_rq == NULL || action == ide_preempt) {
                rq->next = cur_rq;
                drive->queue = rq;
@@ -1407,13 +1535,13 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
                rq->next = cur_rq->next;
                cur_rq->next = rq;
        }
-       if (!hwgroup->active) {
-               do_hwgroup_request(hwgroup);
-               __cli();
-       }
-       if (action == ide_wait  && rq->rq_status != RQ_INACTIVE)
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_drive_cmd", &io_request_lock, flags);
+       do_hwgroup_request("drive_cmd do_hwgroup_request", hwgroup);
+       save_flags(flags);      /* all CPUs; overkill? */
+       cli();                  /* all CPUs; overkill? */
+       if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
                down(&sem);     /* wait for it to be serviced */
-       __restore_flags(flags);
+       restore_flags(flags);   /* all CPUs; overkill? */
        return rq->errors ? -EIO : 0;   /* return -EIO if errors */
 }
 
@@ -1428,6 +1556,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
 int ide_revalidate_disk(kdev_t i_rdev)
 {
        ide_drive_t *drive;
+       ide_hwgroup_t *hwgroup;
        unsigned int p, major, minor;
        long flags;
 
@@ -1435,15 +1564,15 @@ int ide_revalidate_disk(kdev_t i_rdev)
                return -ENODEV;
        major = MAJOR(i_rdev);
        minor = drive->select.b.unit << PARTN_BITS;
-       __save_flags(flags);
-       __cli();
+       hwgroup = HWGROUP(drive);
+       IDE_SPIN_LOCK_IRQSAVE("ide_revalidate_disk", &hwgroup->spinlock, flags);
        if (drive->busy || (drive->usage > 1)) {
-               __restore_flags(flags);
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
                return -EBUSY;
        };
        drive->busy = 1;
        MOD_INC_USE_COUNT;
-       __restore_flags(flags);
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
 
        for (p = 0; p < (1<<PARTN_BITS); ++p) {
                if (drive->part[p].nr_sects > 0) {
@@ -1589,8 +1718,8 @@ void ide_unregister (unsigned int index)
 
        if (index >= MAX_HWIFS)
                return;
-       __save_flags(flags);
-       __cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
        hwif = &ide_hwifs[index];
        if (!hwif->present)
                goto abort;
@@ -1680,7 +1809,7 @@ void ide_unregister (unsigned int index)
        }
        init_hwif_data (index); /* restore hwif data to pristine status */
 abort:
-       __restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
 }
 
 int ide_register (int arg1, int arg2, int irq)
@@ -1719,7 +1848,7 @@ found:
        return hwif->present ? index : -1;
 }
 
-void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
 {
        ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
 
@@ -1798,38 +1927,63 @@ repeat:
 
 int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
 {
-       if (!(setting->rw & SETTING_READ))
-               return -EINVAL;
-       switch(setting->data_type) {
-               case TYPE_BYTE:
-                       return *((u8 *) setting->data);
-               case TYPE_SHORT:
-                       return *((u16 *) setting->data);
-               case TYPE_INT:
-               case TYPE_INTA:
-                       return *((u32 *) setting->data);
-               default:
-                       return -EINVAL;
+       int             val = -EINVAL;
+       unsigned long   flags;
+
+       if ((setting->rw & SETTING_READ)) {
+               IDE_SPIN_LOCK_IRQSAVE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+               switch(setting->data_type) {
+                       case TYPE_BYTE:
+                               val = *((u8 *) setting->data);
+                               break;
+                       case TYPE_SHORT:
+                               val = *((u16 *) setting->data);
+                               break;
+                       case TYPE_INT:
+                       case TYPE_INTA:
+                               val = *((u32 *) setting->data);
+                               break;
+               }
+               IDE_SPIN_UNLOCK_IRQRESTORE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
+       }
+       return val;
+}
+
+int ide_spin_wait_hwgroup (const char *msg, ide_drive_t *drive, unsigned long *flags)
+{
+       ide_hwgroup_t *hwgroup = HWGROUP(drive);
+       unsigned long timeout = jiffies + (3 * HZ);
+
+       IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
+       while (hwgroup->busy) {
+               IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, *flags);
+               __sti();        /* local CPU only; needed for jiffies */
+               if (0 < (signed long)(jiffies - timeout)) {
+                       printk("%s: %s: channel busy\n", drive->name, msg);
+                       return -EBUSY;
+               }
+               IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
        }
+       return 0;
 }
 
 int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
 {
        unsigned long flags;
-       int i, rc = 0;
+       int i;
        u32 *p;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (!(setting->rw & SETTING_WRITE))
                return -EPERM;
        if (val < setting->min || val > setting->max)
                return -EINVAL;
-       __save_flags(flags);
-       __cli();
        if (setting->set)
-               rc = setting->set(drive, val);
-       else switch (setting->data_type) {
+               return setting->set(drive, val);
+       if (ide_spin_wait_hwgroup("ide_write_settings", drive, &flags))
+               return -EBUSY;
+       switch (setting->data_type) {
                case TYPE_BYTE:
                        *((u8 *) setting->data) = val;
                        break;
@@ -1845,8 +1999,8 @@ int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
                                *p = val;
                        break;
        }
-       __restore_flags(flags);
-       return rc;
+       IDE_SPIN_UNLOCK_IRQRESTORE("ide_write_setting4", &HWGROUP(drive)->spinlock, flags);
+       return 0;
 }
 
 static int set_io_32bit(ide_drive_t *drive, int arg)
@@ -1956,7 +2110,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        return 0;
                }
                case BLKFLSBUF:
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        fsync_dev(inode->i_rdev);
                        invalidate_buffers(inode->i_rdev);
                        return 0;
@@ -1965,21 +2119,17 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        return put_user(drive->part[MINOR(inode->i_rdev)&PARTN_MASK].nr_sects, (long *) arg);
 
                case BLKRRPART: /* Re-read partition tables */
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        return ide_revalidate_disk(inode->i_rdev);
 
+               case HDIO_OBSOLETE_IDENTITY:
                case HDIO_GET_IDENTITY:
                        if (MINOR(inode->i_rdev) & PARTN_MASK)
                                return -EINVAL;
                        if (drive->id == NULL)
                                return -ENOMSG;
-#if 0
-                       if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
+                       if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
                                return -EFAULT;
-#else
-                       if (copy_to_user((char *)arg, (char *)drive->id, 142))
-                               return -EFAULT;
-#endif
                        return 0;
 
                case HDIO_GET_NICE:
@@ -1993,7 +2143,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                {
                        byte args[4], *argbuf = args;
                        int argsize = 4;
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if (NULL == (void *) arg)
                                return ide_do_drive_cmd(drive, &rq, ide_wait);
                        if (copy_from_user(args, (void *)arg, 4))
@@ -2016,7 +2166,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                case HDIO_SCAN_HWIF:
                {
                        int args[3];
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if (copy_from_user(args, (void *)arg, 3 * sizeof(int)))
                                return -EFAULT;
                        if (ide_register(args[0], args[1], args[2]) == -1)
@@ -2024,7 +2174,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        return 0;
                }
                case HDIO_SET_NICE:
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if (drive->driver == NULL)
                                return -EPERM;
                        if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
@@ -2311,7 +2461,7 @@ __initfunc(void ide_setup (char *s))
                                goto bad_option;        /* chipset already specified */
                        if (i <= -7 && hw != 0)
                                goto bad_hwif;          /* chipset drivers are for "ide0=" only */
-                       if (ide_hwifs[hw^1].chipset != ide_unknown)
+                       if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
                                goto bad_option;        /* chipset for 2nd port already specified */
                        printk("\n");
                }
@@ -2528,12 +2678,6 @@ __initfunc(static void probe_for_hwifs (void))
                        ide_probe_for_rz100x();
                }
 #endif /* CONFIG_BLK_DEV_RZ1000 */
-#ifdef CONFIG_BLK_DEV_SL82C105
-               {
-                       extern void ide_probe_for_sl82c105(void);
-                       ide_probe_for_sl82c105();
-               }
-#endif /* CONFIG_BLK_DEV_SL82C105 */
 #endif /* CONFIG_BLK_DEV_IDEPCI */
        }
 #endif /* CONFIG_PCI */
@@ -2560,21 +2704,21 @@ __initfunc(void ide_init_builtin_drivers (void))
        probe_for_hwifs ();
 
 #ifdef CONFIG_BLK_DEV_IDE
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
        if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
-               ide_get_lock(&ide_lock, NULL, NULL);
+               ide_get_lock(&ide_lock, NULL, NULL);    /* for atari only */
                disable_irq(ide_hwifs[0].irq);
        }
-#endif /* __mc68000__ */
+#endif /* __mc68000__ || CONFIG_APUS */
 
        (void) ideprobe_init();
 
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
        if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
                enable_irq(ide_hwifs[0].irq);
-               ide_release_lock(&ide_lock);
+               ide_release_lock(&ide_lock);    /* for atari only */
        }
-#endif /* __mc68000__ */
+#endif /* __mc68000__ || CONFIG_APUS */
 #endif /* CONFIG_BLK_DEV_IDE */
 
 #ifdef CONFIG_PROC_FS
@@ -2705,16 +2849,15 @@ int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int versio
 {
        unsigned long flags;
        
-       __save_flags(flags);
-       __cli();
-       if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL ||
-           drive->busy || drive->usage) {
-               __restore_flags(flags);
+       save_flags(flags);              /* all CPUs */
+       cli();                          /* all CPUs */
+       if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) {
+               restore_flags(flags);   /* all CPUs */
                return 1;
        }
        drive->driver = driver;
        setup_driver_defaults(drive);
-       __restore_flags(flags);
+       restore_flags(flags);           /* all CPUs */
        if (drive->autotune != 2) {
                if (driver->supports_dma && HWIF(drive)->dmaproc != NULL)
                        (void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
@@ -2733,10 +2876,10 @@ int ide_unregister_subdriver (ide_drive_t *drive)
 {
        unsigned long flags;
        
-       __save_flags(flags);
-       __cli();
+       save_flags(flags);              /* all CPUs */
+       cli();                          /* all CPUs */
        if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) {
-               __restore_flags(flags);
+               restore_flags(flags);   /* all CPUs */
                return 1;
        }
 #ifdef CONFIG_PROC_FS
@@ -2745,7 +2888,7 @@ int ide_unregister_subdriver (ide_drive_t *drive)
 #endif
        auto_remove_settings(drive);
        drive->driver = NULL;
-       __restore_flags(flags);
+       restore_flags(flags);           /* all CPUs */
        return 0;
 }
 
index 565ffea7dc0765f9d36ae6a1efc50dedd8d42a19..24002dd4eec18c1d5ffd73abcbeba628ccc4ba55 100644 (file)
@@ -204,26 +204,28 @@ typedef struct ide_drive_s {
        unsigned long service_start;    /* time we started last request */
        unsigned long service_time;     /* service time of last request */
        special_t       special;        /* special action flags */
+       byte     keep_settings;         /* restore settings after drive reset */
+       byte     using_dma;             /* disk is using dma for read/write */
+       byte     waiting_for_dma;       /* dma currently in progress */
+       byte     unmask;                /* flag: okay to unmask other irqs */
+       byte     slow;                  /* flag: slow data port */
+       byte     bswap;                 /* flag: byte swap data */
+       byte     dsc_overlap;           /* flag: DSC overlap */
+       byte     nice1;                 /* flag: give potential excess bandwidth */
        unsigned present        : 1;    /* drive is physically present */
        unsigned noprobe        : 1;    /* from:  hdx=noprobe */
-       byte     keep_settings;         /* restore settings after drive reset */
        unsigned busy           : 1;    /* currently doing revalidate_disk() */
        unsigned removable      : 1;    /* 1 if need to do check_media_change */
-       byte     using_dma;             /* disk is using dma for read/write */
        unsigned forced_geom    : 1;    /* 1 if hdx=c,h,s was given at boot */
-       byte     unmask;                /* flag: okay to unmask other irqs */
        unsigned no_unmask      : 1;    /* disallow setting unmask bit */
        unsigned no_io_32bit    : 1;    /* disallow enabling 32bit I/O */
        unsigned nobios         : 1;    /* flag: do not probe bios for drive */
-       byte     slow;                  /* flag: slow data port */
-       unsigned autotune       : 2;    /* 1=autotune, 2=noautotune, 0=default */
        unsigned revalidate     : 1;    /* request revalidation */
-       byte     bswap;                 /* flag: byte swap data */
-       byte     dsc_overlap;           /* flag: DSC overlap */
        unsigned atapi_overlap  : 1;    /* flag: ATAPI overlap (not supported) */
        unsigned nice0          : 1;    /* flag: give obvious excess bandwidth */
-       byte     nice1;                 /* flag: give potential excess bandwidth */
        unsigned nice2          : 1;    /* flag: give a share in our own bandwidth */
+       unsigned doorlocking    : 1;    /* flag: for removable only: door lock/unlock works */
+       unsigned autotune       : 2;    /* 1=autotune, 2=noautotune, 0=default */
 #if FAKE_FDISK_FOR_EZDRIVE
        unsigned remap_0_to_1   : 1;    /* flag: partitioned with ezdrive */
 #endif /* FAKE_FDISK_FOR_EZDRIVE */
@@ -270,7 +272,8 @@ typedef struct ide_drive_s {
  * should either try again later, or revert to PIO for the current request.
  */
 typedef enum { ide_dma_read,   ide_dma_write,  ide_dma_begin,  ide_dma_end,
-               ide_dma_check,  ide_dma_on,     ide_dma_off,    ide_dma_off_quietly
+               ide_dma_check,  ide_dma_on,     ide_dma_off,    ide_dma_off_quietly,
+               ide_dma_test_irq
        } ide_dma_action_t;
 
 typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
@@ -340,7 +343,7 @@ typedef struct hwif_s {
        unsigned        reset      : 1; /* reset after probe */
        unsigned        no_autodma : 1; /* don't automatically enable DMA at boot */
        byte            channel;        /* for dual-port chips: 0=primary, 1=secondary */
-       struct          pci_dev *pci_dev; /* for pci chipsets */
+       struct pci_dev  *pci_dev;       /* for pci chipsets */
        ide_pci_devid_t pci_devid;      /* for pci chipsets: {VID,DID} */
 #if (DISK_RECOVERY_TIME > 0)
        unsigned long   last_time;      /* time when previous rq was done */
@@ -353,14 +356,15 @@ typedef struct hwif_s {
 typedef void (ide_handler_t)(ide_drive_t *);
 
 typedef struct hwgroup_s {
+       spinlock_t              spinlock; /* protects "busy" and "handler" */
        ide_handler_t           *handler;/* irq handler, if active */
+       int                     busy;   /* BOOL: protects all fields below */
        ide_drive_t             *drive; /* current drive */
        ide_hwif_t              *hwif;  /* ptr to current hwif in linked-list */
        struct request          *rq;    /* current request */
        struct timer_list       timer;  /* failsafe timer */
        struct request          wrq;    /* local copy of current write rq */
        unsigned long           poll_timeout;   /* timeout value during long polls */
-       int                     active; /* set when servicing requests */
        } ide_hwgroup_t;
 
 /*
@@ -393,7 +397,7 @@ typedef struct ide_settings_s {
        struct ide_settings_s   *next;
 } ide_settings_t;
 
-void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
+void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
 void ide_remove_setting(ide_drive_t *drive, char *name);
 ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
 int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
@@ -663,6 +667,7 @@ void ide_stall_queue (ide_drive_t *drive, unsigned long timeout);
  */
 struct request **ide_get_queue (kdev_t dev);
 
+int  ide_spin_wait_hwgroup(const char *msg, ide_drive_t *drive, unsigned long *flags);
 void ide_timer_expiry (unsigned long data);
 void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
 void ide_geninit (struct gendisk *gd);
@@ -689,6 +694,9 @@ extern struct file_operations ide_fops[];
 #endif
 
 #ifdef _IDE_C
+#ifdef CONFIG_BLK_DEV_IDE
+int ideprobe_init (void);
+#endif /* CONFIG_BLK_DEV_IDE */
 #ifdef CONFIG_BLK_DEV_IDEDISK
 int idedisk_init (void);
 #endif /* CONFIG_BLK_DEV_IDEDISK */
@@ -722,13 +730,9 @@ int ide_build_dmatable (ide_drive_t *drive);
 void ide_dma_intr  (ide_drive_t *drive);
 int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
 void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
-unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name) __init;
+unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
 #endif
 
-#ifdef CONFIG_BLK_DEV_IDE
-int ideprobe_init (void);
-#endif /* CONFIG_BLK_DEV_IDE */
-
 #ifdef CONFIG_BLK_DEV_PDC4030
 #include "pdc4030.h"
 #define IS_PDC4030_DRIVE (HWIF(drive)->chipset == ide_pdc4030)
index 900ed785a3c89125fa86f17823306f96aec6aa72..d1201086ddd059b4d67f6384e69d346727178594 100644 (file)
@@ -448,7 +448,7 @@ static int loop_get_status(struct loop_device *lo, struct loop_info *arg)
        info.lo_flags = lo->lo_flags;
        strncpy(info.lo_name, lo->lo_name, LO_NAME_SIZE);
        info.lo_encrypt_type = lo->lo_encrypt_type;
-       if (lo->lo_encrypt_key_size && suser()) {
+       if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) {
                info.lo_encrypt_key_size = lo->lo_encrypt_key_size;
                memcpy(info.lo_encrypt_key, lo->lo_encrypt_key,
                       lo->lo_encrypt_key_size);
index 674c378b1fb9711850815b86f38a714e25521999..8b4b487e1e076b9c539a0b9bf54579fb996acff2 100644 (file)
@@ -622,7 +622,7 @@ static int md_ioctl (struct inode *inode, struct file *file,
   int minor, err;
   struct hd_geometry *loc = (struct hd_geometry *) arg;
 
-  if (!suser())
+  if (!capable(CAP_SYS_ADMIN))
     return -EACCES;
 
   if (((minor=MINOR(inode->i_rdev)) & 0x80) &&
index 70e4456682564c525485ff391fdf83ae4a2eb8c9..cd733884c223c0d029646b70b9a86a468c93f945 100644 (file)
@@ -316,7 +316,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
        struct nbd_device *lo;
        int dev, error;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (!inode)
                return -EINVAL;
index f312b251c9c44f56e765317a75325c0bd2be02bf..e7006ed69e401a71beddcea6da7081906071fd6d 100644 (file)
@@ -35,7 +35,8 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
        struct pci_dev *dev = hwif->pci_dev;
        unsigned long flags;
 
-       save_flags(flags); cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        new = *old;
 
        /* adjust IRQ enable bit */
@@ -56,7 +57,7 @@ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
                *old = new;
                (void) pci_write_config_dword(dev, 0x40, new);
        }
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
 }
 
 static void ns87415_selectproc (ide_drive_t *drive)
@@ -66,33 +67,25 @@ static void ns87415_selectproc (ide_drive_t *drive)
 
 static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-       ide_hwif_t *hwif = HWIF(drive);
+       ide_hwif_t      *hwif = HWIF(drive);
+       byte            dma_stat;
 
        switch (func) {
                case ide_dma_end: /* returns 1 on error, 0 otherwise */
-               {
-                       byte dma_stat = inb(hwif->dma_base+2);
-                       int rc = (dma_stat & 7) != 4;
-                       /* from errata: stop DMA, clear INTR & ERROR */
-                       outb(7, hwif->dma_base);
-                       /* clear the INTR & ERROR bits */
-                       outb(dma_stat|6, hwif->dma_base+2);
-                       /* verify good DMA status */
-                       return rc;
-               }
+                       drive->waiting_for_dma = 0;
+                       dma_stat = inb(hwif->dma_base+2);
+                       outb(7, hwif->dma_base);                /* from errata: stop DMA, clear INTR & ERROR */
+                       outb(dma_stat|6, hwif->dma_base+2);     /* clear the INTR & ERROR bits */
+                       return (dma_stat & 7) != 4;             /* verify good DMA status */
                case ide_dma_write:
                case ide_dma_read:
-                       /* select DMA xfer */
-                       ns87415_prepare_drive(drive, 1);
-                       /* use standard DMA stuff */
-                       if (!ide_dmaproc(func, drive))
+                       ns87415_prepare_drive(drive, 1);        /* select DMA xfer */
+                       if (!ide_dmaproc(func, drive))          /* use standard DMA stuff */
                                return 0;
-                       /* DMA failed: select PIO xfer */
-                       ns87415_prepare_drive(drive, 0);
+                       ns87415_prepare_drive(drive, 0);        /* DMA failed: select PIO xfer */
                        return 1;
                default:
-                       /* use standard DMA stuff */
-                       return ide_dmaproc(func, drive);
+                       return ide_dmaproc(func, drive);        /* use standard DMA stuff */
        }
 }
 
@@ -100,8 +93,7 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
 {
        struct pci_dev *dev = hwif->pci_dev;
        unsigned int ctrl, using_inta;
-       byte progif, stat;
-       int timeout;
+       byte progif;
 
        /*
         * We cannot probe for IRQ: both ports share common IRQ on INTA.
@@ -134,6 +126,9 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
                pci_write_config_byte(dev, 0x55, 0xee);
 
 #ifdef __sparc_v9__
+{
+               int     timeout;
+               byte    stat;
                /*
                 * XXX: Reset the device, if we don't it will not respond
                 *      to SELECT_DRIVE() properly during first probe_hwif().
@@ -148,6 +143,7 @@ __initfunc(void ide_init_ns87415 (ide_hwif_t *hwif))
                        if (stat == 0xff)
                                break;
                } while ((stat & BUSY_STAT) && --timeout);
+}
 #endif
        }
        if (!using_inta)
index a6be01938b9907b607921cd74955c8068426ef60..41b87fbbe3b50c9a6142c2bee6b4eba1f8646ae6 100644 (file)
@@ -242,8 +242,8 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
                hwif->name, ax, second.data_time, second.recovery_time, drdy);
 #endif
 
-       save_flags(flags);
-       cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
 
        reg_base = hwif->io_ports[IDE_DATA_OFFSET];
        outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */
@@ -268,7 +268,7 @@ static void opti621_tune_drive (ide_drive_t *drive, byte pio)
        write_reg(misc, MISC_REG);      /* set address setup, DRDY timings,   */
                                        /*  and read prefetch for both drives */
 
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
 }
 
 /*
index aa431ae33dfaeefd93563036ee7cf3ff3617df36..c2f9473bc661342de4a92bfca9e9ab9fa67c2fd2 100644 (file)
@@ -466,7 +466,7 @@ static int pd_ioctl(struct inode *inode,struct file *file,
                 put_user(pd_hd[dev].start_sect,(long *)&geo->start);
                 return 0;
             case BLKRASET:
-                if(!suser()) return -EACCES;
+                if(!capable(CAP_SYS_ADMIN)) return -EACCES;
                 if(!(inode->i_rdev)) return -EINVAL;
                 if(arg > 0xff) return -EINVAL;
                 read_ahead[MAJOR(inode->i_rdev)] = arg;
@@ -484,12 +484,14 @@ static int pd_ioctl(struct inode *inode,struct file *file,
                 put_user(pd_hd[dev].nr_sects,(long *) arg);
                 return (0);
             case BLKFLSBUF:
-                if(!suser())  return -EACCES;
+                if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                 if(!(inode->i_rdev)) return -EINVAL;
                 fsync_dev(inode->i_rdev);
                 invalidate_buffers(inode->i_rdev);
                 return 0;
             case BLKRRPART:
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EACCES;
                 return pd_revalidate(inode->i_rdev);
             RO_IOCTLS(inode->i_rdev,arg);
             default:
index 00d629ddde9d6711fea142fef1f1441685cb71a6..b894e2cc9b6a59a793cf7f6376ac855e489f176e 100644 (file)
@@ -416,7 +416,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
                 put_user(0,(long *)&geo->start);
                 return 0;
             case BLKRASET:
-                if(!suser()) return -EACCES;
+                if(!capable(CAP_SYS_ADMIN)) return -EACCES;
                 if(!(inode->i_rdev)) return -EINVAL;
                 if(arg > 0xff) return -EINVAL;
                 read_ahead[MAJOR(inode->i_rdev)] = arg;
@@ -434,7 +434,7 @@ static int pf_ioctl(struct inode *inode,struct file *file,
                 put_user(PF.capacity,(long *) arg);
                 return (0);
             case BLKFLSBUF:
-                if(!suser())  return -EACCES;
+                if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                 if(!(inode->i_rdev)) return -EINVAL;
                 fsync_dev(inode->i_rdev);
                 invalidate_buffers(inode->i_rdev);
index 30baff570293fd17911aa223c058467ebd253700..b5b13b9cbb08919c1b5bf35b8003297feadb0953 100644 (file)
@@ -327,15 +327,9 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
            do {
                stat=GET_STAT();
                if(stat & DRQ_STAT) {
-/*                    unsigned long flags;
-                    save_flags(flags);
-                    cli();
                     disable_irq(HWIF(drive)->irq);
-*/
                    ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
-/*                    enable_irq(HWIF(drive)->irq);
-                    restore_flags(flags);
-*/
+                    enable_irq(HWIF(drive)->irq);
                    return;
                }
                if(IN_BYTE(IDE_SELECT_REG) & 0x01)
@@ -353,7 +347,7 @@ void do_pdc4030_io (ide_drive_t *drive, struct request *rq)
                return;
            }
            if (!drive->unmask)
-               cli();
+               __cli();        /* local CPU only */
            HWGROUP(drive)->wrq = *rq; /* scratchpad */
            promise_write(drive);
            return;
index cf13eccafb26fe722e7130e97e3b4b38148ffb7a..bef50bd36159b0c1d7eb6dbba1095e15b17e1d15 100644 (file)
@@ -1091,7 +1091,7 @@ static int ps2esdi_ioctl(struct inode *inode,
                        }
                        break;
                case BLKRASET:
-                       if (!suser())
+                       if (!capable(CAP_SYS_ADMIN))
                                return -EACCES;
                        if (!inode->i_rdev)
                                return -EINVAL;
@@ -1109,7 +1109,7 @@ static int ps2esdi_ioctl(struct inode *inode,
                        }
                        break;
                case BLKFLSBUF:
-                       if (!suser())
+                       if (!capable(CAP_SYS_ADMIN))
                                return -EACCES;
                        if (!inode->i_rdev)
                                return -EINVAL;
@@ -1118,6 +1118,8 @@ static int ps2esdi_ioctl(struct inode *inode,
                        return 0;
 
                case BLKRRPART:
+                        if (!capable(CAP_SYS_ADMIN)) 
+                               return -EACCES;
                        return (ps2esdi_reread_partitions(inode->i_rdev));
                        RO_IOCTLS(inode->i_rdev, arg);
                }
index 9c13bfea98e49678bc8f4f479e58913bd7f3deca..9c1d0ed71317b63173e06c44f02395f981a31a46 100644 (file)
@@ -49,13 +49,13 @@ static void tune_qd6580 (ide_drive_t *drive, byte pio)
 
        pio = ide_get_best_pio_mode(drive, pio, 3, NULL);
 
-       save_flags(flags);
-       cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
        outb_p(0x8d,0xb0);
        outb_p(0x0 ,0xb2);
        outb_p(((pio+1)<<4)|0x0f,0xb3);
        inb(0x3f6);
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
 }
 
 void init_qd6580 (void)
index 180a090d12633f8ac521f46e19ab006cdbd6d711..a3366d04bd72f18d51e45af36aed6cadf0ce8546 100644 (file)
@@ -164,7 +164,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
 
        switch (cmd) {
                case BLKFLSBUF:
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        invalidate_buffers(inode->i_rdev);
                        break;
                case BLKGETSIZE:   /* Return device size */
index 83426bc5eeb5393e73bb8a57f916b7efe6e0b12b..ef05e4656f7428352b657abf6c2ea72dca221c8b 100644 (file)
@@ -19,8 +19,9 @@ int chrp_ide_ports_known = 0;
 ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
 ide_ioreg_t chrp_idedma_regbase;
 
-void ide_init_sl82c105(struct pci_dev *dev) {
-
+void ide_init_sl82c105(ide_hwif_t *hwif)
+{
+       struct pci_dev *dev = hwif->pci_dev;
        unsigned short t16;
        unsigned int t32;
 
@@ -37,15 +38,7 @@ void ide_init_sl82c105(struct pci_dev *dev) {
        pci_write_config_dword(dev, 0x40, 0x10ff08a1);
 }
 
-
-void ide_probe_for_sl82c105(void)
-{
-       struct pci_dev *dev = NULL;
-
-        while ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev)))
-                ide_init_sl82c105(dev);
-}
-
+#if 0  /* nobody ever calls these.. ?? */
 void chrp_ide_probe(void) {
 
        struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -75,4 +68,4 @@ void chrp_ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int *irq)
         if (irq != NULL)
                 *irq = chrp_ide_irq;
 }
-
+#endif
index 474d434a2d308c1a2c6a6cac257d444439e9b5a7..2b067884967957746809970250008c3fee11ffb6 100644 (file)
@@ -148,8 +148,8 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
        /* select PIO or DMA */
        reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);
 
-       save_flags(flags);
-       cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
 
        if (reg != hwif->select_data) {
                hwif->select_data = reg;
@@ -164,7 +164,7 @@ static void trm290_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
                outw(reg, hwif->config_data+3);
        }
 
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
 }
 
 static void trm290_selectproc (ide_drive_t *drive)
@@ -189,15 +189,20 @@ static int trm290_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
                                break;          /* try PIO instead of DMA */
                        trm290_prepare_drive(drive, 1); /* select DMA xfer */
                        outl(virt_to_bus(hwif->dmatable)|reading|writing, hwif->dma_base);
+                       drive->waiting_for_dma = 1;
                        outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
                        if (drive->media != ide_disk)
                                return 0;
                        ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);
                        OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
+                       return 0;
                case ide_dma_begin:
                        return 0;
                case ide_dma_end:
+                       drive->waiting_for_dma = 0;
                        return (inw(hwif->dma_base+2) != 0x00ff);
+               case ide_dma_test_irq:
+                       return (inw(hwif->dma_base+2) == 0x00ff);
                default:
                        return ide_dmaproc(func, drive);
        }
@@ -226,8 +231,8 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
                printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data);
        }
 
-       save_flags(flags);
-       cli();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        /* put config reg into first byte of hwif->select_data */
        outb(0x51|(hwif->channel<<3), hwif->config_data+1);
        hwif->select_data = 0x21;                       /* select PIO as default */
@@ -235,13 +240,13 @@ __initfunc(void ide_init_trm290 (ide_hwif_t *hwif))
        reg = inb(hwif->config_data+3);                 /* get IRQ info */
        reg = (reg & 0x10) | 0x03;                      /* mask IRQs for both ports */
        outb(reg, hwif->config_data+3);
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
 
        if ((reg & 0x10))
                hwif->irq = hwif->channel ? 15 : 14;    /* legacy mode */
        else if (!hwif->irq && hwif->mate && hwif->mate->irq)
                hwif->irq = hwif->mate->irq;            /* sharing IRQ with mate */
-       ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 2);
+       ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
        hwif->dmaproc = &trm290_dmaproc;
        hwif->selectproc = &trm290_selectproc;
        hwif->no_autodma = 1;                           /* play it safe for now */
index 8856dad35c723ae07a1e8ed980ac025ec0ed43d0..77121ca3e017de88e9795c7bf46c4ea5315d14ef 100644 (file)
@@ -112,39 +112,39 @@ static void tune_umc (ide_drive_t *drive, byte pio)
 
        pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
        printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]);
-       save_flags(flags);
-       cli();
+       save_flags(flags);      /* all CPUs */
+       cli();                  /* all CPUs */
        if (hwgroup && hwgroup->handler != NULL) {
                printk("umc8672: other interface is busy: exiting tune_umc()\n");
        } else {
                current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
                umc_set_speeds (current_speeds);
        }
-       restore_flags(flags);
+       restore_flags(flags);   /* all CPUs */
 }
 
 void init_umc8672 (void)       /* called from ide.c */
 {
        unsigned long flags;
 
-       save_flags(flags);
-       cli ();
+       __save_flags(flags);    /* local CPU only */
+       __cli();                /* local CPU only */
        if (check_region(0x108, 2)) {
-               restore_flags(flags);
+               __restore_flags(flags);
                printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
                return;
        }
        outb_p (0x5A,0x108); /* enable umc */
        if (in_umc (0xd5) != 0xa0)
        {
-               restore_flags(flags);
+               __restore_flags(flags); /* local CPU only */
                printk ("umc8672: not found\n");
                return;  
        }
        outb_p (0xa5,0x108); /* disable umc */
 
        umc_set_speeds (current_speeds);
-       restore_flags(flags);
+       __restore_flags(flags); /* local CPU only */
 
        request_region(0x108, 2, "umc8672");
        ide_hwifs[0].chipset = ide_umc8672;
index 7a26e28ac33c38b243948012cfd8da68485e79e8..b7d604db884aa879fac1eab600ba354b30f5bb26 100644 (file)
@@ -338,7 +338,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
                        return copy_to_user(geometry, &g, sizeof g) ? -EFAULT : 0;
                }
                case BLKRASET:
-                       if(!suser()) return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if(arg > 0xff) return -EINVAL;
                        read_ahead[MAJOR(inode->i_rdev)] = arg;
                        return 0;
@@ -348,12 +348,12 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
                        if (!arg) return -EINVAL;
                        return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
                case BLKFLSBUF:   /* Return devices size */
-                       if(!suser())  return -EACCES;
+                       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
                        fsync_dev(inode->i_rdev);
                        invalidate_buffers(inode->i_rdev);
                        return 0;
                case HDIO_SET_DMA:
-                       if (!suser()) return -EACCES;
+                       if (!capable(CAP_SYS_ADMIN)) return -EACCES;
                        if (xdc_busy) return -EBUSY;
                        nodma = !arg;
                        if (nodma && xd_dma_buffer) {
@@ -366,6 +366,8 @@ static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
                case HDIO_GET_MULTCOUNT:
                        return put_user(xd_maxsectors, (long *) arg);
                case BLKRRPART:
+                       if (!capable(CAP_SYS_ADMIN)) 
+                               return -EACCES;
                        return xd_reread_partitions(inode->i_rdev);
                RO_IOCTLS(inode->i_rdev,arg);
                default:
index a3b3e2989689be079c0d410f19c389860828ad42..5397945953425545711cc68b42c5024cce0c7a97 100644 (file)
@@ -4189,7 +4189,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
        switch (cmd)            /* Sun-compatible */
        {
        case DDIOCSDBG:         /* DDI Debug */
-               if (!suser()) RETURN_UP(-EPERM);
+               if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
                i=sbpcd_dbg_ioctl(arg,1);
                RETURN_UP(i);
        case CDROMRESET:      /* hard reset the drive */
@@ -4478,7 +4478,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
        } /* end of CDROMREADAUDIO */
                
        case BLKRASET:
-               if(!suser()) RETURN_UP(-EACCES);
+               if(!capable(CAP_SYS_ADMIN)) RETURN_UP(-EACCES);
                if(!(cdi->dev)) RETURN_UP(-EINVAL);
                if(arg > 0xff) RETURN_UP(-EINVAL);
                read_ahead[MAJOR(cdi->dev)] = arg;
index f4fcf4f7bb92371663f1ccab88918cf328f7fe32..c461cf7098f5bf80260cd9a56627adaede8ab98b 100644 (file)
@@ -1050,7 +1050,7 @@ static int do_open(struct inode * inode, struct file * filp)
         * we might close the device immediately without doing a
         * privileged operation -- cevans
         */
-       as->suser = suser();
+       as->suser = capable(CAP_SYS_ADMIN);
        as->next = user_list;
        user_list = as;
        filp->private_data = as;
index ec66585cfe1b913bab9e29848d845ad78bbb4fb4..97d5794f14e448dce9ec98f2ae7793b4b14afdcc 100644 (file)
@@ -1581,7 +1581,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                case VIDIOCSFBUF:
                {
                        struct video_buffer v;
-                       if(!suser())
+                       if(!capable(CAP_SYS_ADMIN))
                                return -EPERM;
                        if(copy_from_user(&v, arg,sizeof(v)))
                                return -EFAULT;
@@ -1680,7 +1680,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        return 0;
 
                case BTTV_WRITEE:
-                       if(!suser())
+                       if(!capable(CAP_SYS_ADMIN))
                                return -EPERM;
                        if(copy_from_user((void *) eedata, (void *) arg, 256))
                                return -EFAULT;
@@ -1688,7 +1688,7 @@ static int bttv_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
                        return 0;
 
                case BTTV_READEE:
-                       if(!suser())
+                       if(!capable(CAP_SYS_ADMIN))
                                return -EPERM;
                        readee(&(btv->i2c), eedata);
                        if(copy_to_user((void *) arg, (void *) eedata, 256))
index dc437cc2f083888b41819b4970a08bd83e72375c..06d80edf34b055396d9536d96b115b03196e3464 100644 (file)
@@ -331,7 +331,7 @@ int vc_allocate(unsigned int i)             /* return 0 on success */
            long p, q;
 
            /* prevent users from taking too much memory */
-           if (i >= MAX_NR_USER_CONSOLES && !suser())
+           if (i >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
              return -EPERM;
 
            /* due to the granularity of kmalloc, we waste some memory here */
index 2ea9cb86f53bd90c199e861b808f36408d4b046e..553bf273bc634a2494ad3b346685f9bc2c5266ff 100644 (file)
@@ -926,7 +926,7 @@ static int startup(struct esp_struct * info)
                             "esp serial", info);
 
        if (retval) {
-               if (suser()) {
+               if (capable(CAP_SYS_ADMIN)) {
                        if (info->tty)
                                set_bit(TTY_IO_ERROR,
                                        &info->tty->flags);
@@ -1499,7 +1499,7 @@ static int set_serial_info(struct esp_struct * info,
        if (change_irq && (info->line % 8))
                return -EINVAL;
 
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if (change_irq || 
                    (new_serial.close_delay != info->close_delay) ||
                    ((new_serial.flags & ~ASYNC_USR_MASK) !=
index 3b80c207f54e1a7df71d528d3055370dacd97feb..da2010ceba40603c9bd1a36de635b1c3b7fee9c8 100644 (file)
@@ -1342,9 +1342,9 @@ static int mtiocftcmd(struct mtftcmd *ftcmd, int arg_size)
        TRACE_FUN(ft_t_flow);
 
        TRACE(ft_t_noise, "Mag tape ioctl command: MTIOCFTCMD");
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                TRACE_ABORT(-EPERM, ft_t_info,
-                           "only the superuser may send raw qic-117 commands");
+                           "need CAP_SYS_ADMIN capability to send raw qic-117 commands");
        }
        if (zft_qic_mode) {
                TRACE_ABORT(-EACCES, ft_t_info,
index 2e0dd373693769d9e111d7875d6f3142749e30c3..404f9c88c77bf5949714c1e67f738effa28051fa 100644 (file)
@@ -1774,7 +1774,7 @@ static int stli_setserial(stliport_t *portp, struct serial_struct *sp)
 #endif
 
        copy_from_user(&sio, sp, sizeof(struct serial_struct));
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((sio.baud_base != portp->baud_base) ||
                    (sio.close_delay != portp->close_delay) ||
                    ((sio.flags & ~ASYNC_USR_MASK) !=
index 2e2ffc3419a3c28570de6f66132923e6c230954e..7df3eb655b7d8e7f50752a2bc50f39256d200660 100644 (file)
@@ -13,7 +13,7 @@
  * lp_read (Status readback) support added by Carsten Gross,
  *                                             carsten@sol.wohnheim.uni-ulm.de
  * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
- * parport_sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
+ * Parport sharing hacking by Andrea Arcangeli <arcangeli@mbox.queen.it>
  * Fixed kernel_(to/from)_user memory copy to check for errors
  *                             by Riccardo Facchetti <fizban@tin.it>
  */
@@ -75,6 +75,8 @@
 #include <linux/delay.h>
 
 #include <linux/parport.h>
+#undef LP_STATS
+#undef LP_NEED_CAREFUL
 #include <linux/lp.h>
 
 #include <asm/irq.h>
 struct lp_struct lp_table[LP_NO] =
 {
        [0 ... LP_NO-1] = {NULL, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT,
-                          NULL, 0, 0, 0, {0}}
+                          NULL,
+#ifdef LP_STATS
+                          0, 0, {0},
+#endif
+                          NULL, 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(minor, status) \
-  ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
+  ((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)) == \
+   ((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
 
 #undef LP_DEBUG
 #undef LP_READ_DEBUG
@@ -108,8 +116,8 @@ static int lp_preempt(void *handle)
 {
        struct lp_struct *lps = (struct lp_struct *)handle;
 
-       if (waitqueue_active (&lps->dev->wait_q))
-               wake_up_interruptible(&lps->dev->wait_q);
+       if (waitqueue_active (&lps->wait_q))
+               wake_up_interruptible(&lps->wait_q);
 
        /* Don't actually release the port now */
        return 1;
@@ -157,31 +165,29 @@ static int lp_reset(int minor)
 
 static inline int lp_char(char lpchar, int minor)
 {
-       int status;
+       unsigned char status;
        unsigned int wait = 0;
        unsigned long count = 0;
+#ifdef LP_STATS
        struct lp_stats *stats;
+#endif
 
-       for (;;) {
+       for (;;)
+       {
                lp_yield(minor);
                status = r_str (minor);
-               if (++count == LP_CHAR(minor))
+               if (LP_READY(minor, status))
+                       break;
+               if (!LP_POLLED(minor) || ++count == LP_CHAR(minor) ||
+                    signal_pending(current))
                        return 0;
-               if (LP_POLLING(minor))
-               {
-                       if (LP_READY(minor, status))
-                               break;
-               } else {
-                       if (!LP_READY(minor, status))
-                               return 0;
-                       else
-                               break;
-               }
        }
 
        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__
@@ -200,6 +206,8 @@ static inline int lp_char(char lpchar, int minor)
 #endif
        /* take strobe low */
        w_ctr(minor, LP_PSELECP | LP_PINITP);
+
+#ifdef LP_STATS
        /* update waittime statistics */
        if (count > stats->maxwait) {
 #ifdef LP_DEBUG
@@ -212,6 +220,7 @@ static inline int lp_char(char lpchar, int minor)
            stats->meanwait - count;
        stats->meanwait = (255 * stats->meanwait + count + 128) / 256;
        stats->mdev = ((127 * stats->mdev) + wait + 64) / 128;
+#endif
 
        return 1;
 }
@@ -220,13 +229,13 @@ static void lp_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct lp_struct *lp_dev = (struct lp_struct *) dev_id;
 
-       if (waitqueue_active (&lp_dev->dev->wait_q))
-               wake_up_interruptible(&lp_dev->dev->wait_q);
+       if (waitqueue_active (&lp_dev->wait_q))
+               wake_up_interruptible(&lp_dev->wait_q);
 }
 
 static void lp_error(int minor)
 {
-       if (LP_POLLING(minor) || LP_PREEMPTED(minor)) {
+       if (LP_POLLED(minor) || LP_PREEMPTED(minor)) {
                current->state = TASK_INTERRUPTIBLE;
                current->timeout = jiffies + LP_TIMEOUT_POLLED;
                lp_parport_release(minor);
@@ -236,7 +245,7 @@ static void lp_error(int minor)
 }
 
 static int lp_check_status(int minor) {
-       static unsigned char last = 0;
+       unsigned int last = lp_table[minor].last_error;
        unsigned char status = r_str(minor);
        if ((status & LP_POUTPA)) {
                if (last != LP_POUTPA) {
@@ -256,6 +265,8 @@ static int lp_check_status(int minor) {
        }
        else last = 0;
 
+       lp_table[minor].last_error = last;
+
        if (last != 0) {
                if (LP_F(minor) & LP_ABORT)
                        return 1;
@@ -265,7 +276,7 @@ static int lp_check_status(int minor) {
        return 0;
 }
 
-static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
+static int lp_write_buf(unsigned int minor, const char *buf, int count)
 {
        unsigned long copy_size;
        unsigned long total_bytes_written = 0;
@@ -275,9 +286,11 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
 
        if (minor >= LP_NO)
                return -ENXIO;
-       if (lp_table[minor].dev == NULL)
+       if (lp->dev == NULL)
                return -ENXIO;
 
+       lp_table[minor].last_error = 0;
+
        do {
                bytes_written = 0;
                copy_size = (count <= LP_BUFFER_SIZE ? count : LP_BUFFER_SIZE);
@@ -289,55 +302,69 @@ static inline int lp_write_buf(unsigned int minor, const char *buf, int count)
                        if (lp_char(lp->lp_buffer[bytes_written], minor)) {
                                --copy_size;
                                ++bytes_written;
-                               lp_table[minor].runchars++;
+#ifdef LP_STATS
+                               lp->runchars++;
+#endif
                        } else {
                                int rc = total_bytes_written + bytes_written;
-                               if (lp_table[minor].runchars > LP_STAT(minor).maxrun)
-                                       LP_STAT(minor).maxrun = lp_table[minor].runchars;
+
+#ifdef LP_STATS
+                               if (lp->runchars > LP_STAT(minor).maxrun)
+                                       LP_STAT(minor).maxrun = lp->runchars;
                                LP_STAT(minor).sleeps++;
+#endif
 
-                               if (LP_POLLING(minor)) {
-                               lp_polling:
+                               if (signal_pending(current)) {
+                                       if (total_bytes_written + bytes_written)
+                                               return total_bytes_written + bytes_written;
+                                       else
+                                               return -EINTR;
+                               }
+
+#ifdef LP_STATS
+                               lp->runchars = 0;
+#endif
+
+                               if (LP_POLLED(minor)) {
                                        if (lp_check_status(minor))
                                                return rc ? rc : -EIO;
-#ifdef LP_DEBUG
-                                       printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp_table[minor].runchars, LP_TIME(minor));
+                               lp_polling:
+#if defined(LP_DEBUG) && defined(LP_STATS)
+                                       printk(KERN_DEBUG "lp%d sleeping at %d characters for %d jiffies\n", minor, lp->runchars, LP_TIME(minor));
 #endif
                                        current->state = TASK_INTERRUPTIBLE;
                                        current->timeout = jiffies + LP_TIME(minor);
                                        lp_schedule (minor);
                                } else {
                                        cli();
-                                       if (LP_PREEMPTED(minor)) {
+                                       if (LP_PREEMPTED(minor))
+                                       {
+                                               /*
+                                                * We can' t sleep on the interrupt
+                                                * since another pardevice need the port.
+                                                */
                                                sti();
                                                goto lp_polling;
                                        }
-                                       enable_irq(lp->dev->port->irq);
-                                       w_ctr(minor, LP_PSELECP|LP_PINITP|LP_PINTEN);
+                                       w_ctr(minor, LP_PSELECP | LP_PINITP | LP_PINTEN);
                                        status = r_str(minor);
-                                       if ((!(status & LP_PACK) || (status & LP_PBUSY))
-                                           && LP_CAREFUL_READY(minor, status)) {
+                                       if (!(status & LP_PACK) || (status & LP_PBUSY))
+                                       {
+                                               /*
+                                                * The interrupt is happened in the
+                                                * meantime so don' t wait for it.
+                                                */
                                                w_ctr(minor, LP_PSELECP | LP_PINITP);
                                                sti();
                                                continue;
                                        }
                                        current->timeout = jiffies + LP_TIMEOUT_INTERRUPT;
-                                       interruptible_sleep_on(&lp->dev->wait_q);
-                                       disable_irq(lp->dev->port->irq);
+                                       interruptible_sleep_on(&lp->wait_q);
                                        w_ctr(minor, LP_PSELECP | LP_PINITP);
                                        sti();
                                        if (lp_check_status(minor))
                                                return rc ? rc : -EIO;
                                }
-
-                               lp_table[minor].runchars = 0;
-
-                               if (signal_pending(current)) {
-                                       if (total_bytes_written + bytes_written)
-                                               return total_bytes_written + bytes_written;
-                                       else
-                                               return -EINTR;
-                               }
                        }
                }
 
@@ -356,10 +383,12 @@ static ssize_t lp_write(struct file * file, const char * buf,
        unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
        ssize_t retv;
 
+#ifdef LP_STATS
        if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
                lp_table[minor].runchars = 0;
 
        lp_table[minor].lastcall = jiffies;
+#endif
 
        /* Claim Parport or sleep until it becomes available
         */
@@ -495,9 +524,8 @@ static int lp_open(struct inode * inode, struct file * file)
                return -ENXIO;
        if ((LP_F(minor) & LP_EXIST) == 0)
                return -ENXIO;
-       if (LP_F(minor) & LP_BUSY)
+       if (test_and_set_bit(LP_BUSY_BIT_POS, &LP_F(minor)) & LP_BUSY)
                return -EBUSY;
-       LP_F(minor) |= LP_BUSY;
 
        MOD_INC_USE_COUNT;
 
@@ -543,8 +571,8 @@ static int lp_release(struct inode * inode, struct file * file)
 
        kfree_s(lp_table[minor].lp_buffer, LP_BUFFER_SIZE);
        lp_table[minor].lp_buffer = NULL;
-       LP_F(minor) &= ~LP_BUSY;
        MOD_DEC_USE_COUNT;
+       LP_F(minor) &= ~LP_BUSY;
        return 0;
 }
 
@@ -581,12 +609,14 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        else
                                LP_F(minor) &= ~LP_ABORTOPEN;
                        break;
+#ifdef LP_NEED_CAREFUL
                case LPCAREFUL:
                        if (arg)
                                LP_F(minor) |= LP_CAREFUL;
                        else
                                LP_F(minor) &= ~LP_CAREFUL;
                        break;
+#endif
                case LPWAIT:
                        LP_WAIT(minor) = arg;
                        break;
@@ -609,6 +639,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                case LPRESET:
                        lp_reset(minor);
                        break;
+#ifdef LP_STATS
                case LPGETSTATS:
                        if (copy_to_user((int *) arg, &LP_STAT(minor),
                                        sizeof(struct lp_stats)))
@@ -617,6 +648,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                                memset(&LP_STAT(minor), 0,
                                                sizeof(struct lp_stats));
                        break;
+#endif
                case LPGETFLAGS:
                        status = LP_F(minor);
                        if (copy_to_user((int *) arg, &status, sizeof(int)))
index 329ac7b326a2b73875745820d60d33316a94a31d..fba8c7d5125f05ac5856bec3ce51f40146c7fd96 100644 (file)
@@ -285,7 +285,7 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
        switch( cmd ) {
 
          case NVRAM_INIT:                      /* initialize NVRAM contents and checksum */
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return( -EACCES );
 
                save_flags(flags);
@@ -301,7 +301,7 @@ static int nvram_ioctl( struct inode *inode, struct file *file,
          case NVRAM_SETCKS:            /* just set checksum, contents unchanged
                                                                 * (maybe useful after checksum garbaged
                                                                 * somehow...) */
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return( -EACCES );
 
                save_flags(flags);
index 226694a7145e1fcd4056e48a71808afc54e92088..13d5d6d36de1ed6909ae6bba84adf9d72a1f08c5 100644 (file)
@@ -1199,7 +1199,7 @@ random_ioctl(struct inode * inode, struct file * file,
                put_user(ent_count, (int *) arg);
                return 0;
        case RNDADDTOENTCNT:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                retval = verify_area(VERIFY_READ, (void *) arg, sizeof(int));
                if (retval)
@@ -1228,7 +1228,7 @@ random_ioctl(struct inode * inode, struct file * file,
                        wake_up_interruptible(&random_read_wait);
                return 0;
        case RNDGETPOOL:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                p = (int *) arg;
                retval = verify_area(VERIFY_WRITE, (void *) p, sizeof(int));
@@ -1249,7 +1249,7 @@ random_ioctl(struct inode * inode, struct file * file,
                        return -EFAULT;
                return 0;
        case RNDADDENTROPY:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                p = (int *) arg;
                retval = verify_area(VERIFY_READ, (void *) p, 2*sizeof(int));
@@ -1287,13 +1287,13 @@ random_ioctl(struct inode * inode, struct file * file,
                        wake_up_interruptible(&random_read_wait);
                return 0;
        case RNDZAPENTCNT:
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                random_state.entropy_count = 0;
                return 0;
        case RNDCLEARPOOL:
                /* Clear the entropy pool and associated counters. */
-               if (!suser())
+               if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                rand_clear_pool();
                return 0;
index bed251b19ec9d360652fc9f77263c4fab33f2778..b854fa33804923c2fb42cbbb6639d0e2d8a3a8d0 100644 (file)
@@ -1447,7 +1447,7 @@ extern inline int rc_set_serial_info(struct riscom_port * port,
        change_speed = ((port->flags & ASYNC_SPD_MASK) !=
                        (tmp.flags & ASYNC_SPD_MASK));
        
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((tmp.close_delay != port->close_delay) ||
                    (tmp.closing_wait != port->closing_wait) ||
                    ((tmp.flags & ~ASYNC_USR_MASK) !=
index 901077455a45c306805e0bbbe9608b5223f4a4aa..cb4e9d4982eaf9c076a508647beeec58018869d8 100644 (file)
@@ -1315,7 +1315,7 @@ static int set_config(struct r_port * info, struct rocket_config * new_info)
        if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
                return -EFAULT;
 
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((new_serial.flags & ~ROCKET_USR_MASK) !=
                    (info->flags & ~ROCKET_USR_MASK))
                        return -EPERM;
index 9edca16836b073e1d84531de10dd0669d0f3b6b9..5f827bed9719546416c78f1812dc93f35859b7ba 100644 (file)
@@ -220,7 +220,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                 * We don't really want Joe User enabling more
                 * than 64Hz of interrupts on a multi-user machine.
                 */
-               if ((rtc_freq > 64) && (!suser()))
+               if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
                        return -EACCES;
 
                if (!(rtc_status & RTC_TIMER_ON)) {
@@ -308,7 +308,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                unsigned int yrs;
                unsigned long flags;
                        
-               if (!suser())
+               if (!capable(CAP_SYS_TIME))
                        return -EACCES;
 
                if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
@@ -394,7 +394,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                 * We don't really want Joe User generating more
                 * than 64Hz of interrupts on a multi-user machine.
                 */
-               if ((arg > 64) && (!suser()))
+               if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
                        return -EACCES;
 
                while (arg > (1<<tmp))
@@ -429,7 +429,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                if (arg < 1900)
                        return -EINVAL;
 
-               if (!suser())
+               if (!capable(CAP_SYS_TIME))
                        return -EACCES;
 
                epoch = arg;
index 2113bac7d3ed72deac1a4c1f573d92b89c2f5720..5ac51c5c6243403f2fb6d899455a83a1cec4adbe 100644 (file)
@@ -973,7 +973,7 @@ static int startup(struct async_struct * info)
         * here.
         */
        if (serial_inp(info, UART_LSR) == 0xff) {
-               if (suser()) {
+               if (capable(CAP_SYS_ADMIN)) {
                        if (info->tty)
                                set_bit(TTY_IO_ERROR, &info->tty->flags);
                } else
@@ -1005,7 +1005,7 @@ static int startup(struct async_struct * info)
                retval = request_irq(state->irq, handler, IRQ_T(info),
                                     "serial", NULL);
                if (retval) {
-                       if (suser()) {
+                       if (capable(CAP_SYS_ADMIN)) {
                                if (info->tty)
                                        set_bit(TTY_IO_ERROR,
                                                &info->tty->flags);
@@ -1638,7 +1638,7 @@ static int set_serial_info(struct async_struct * info,
        change_port = (new_serial.port != state->port) ||
                (new_serial.hub6 != state->hub6);
   
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if (change_irq || change_port ||
                    (new_serial.baud_base != state->baud_base) ||
                    (new_serial.type != state->type) ||
@@ -1837,7 +1837,7 @@ static int do_autoconfig(struct async_struct * info)
 {
        int                     retval;
        
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        
        if (info->state->count > 1)
@@ -1922,7 +1922,7 @@ static int set_multiport_struct(struct async_struct * info,
        int     retval;
        void (*handler)(int, void *, struct pt_regs *);
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        state = info->state;
        
index ef5e6f7c7b06cf223b51985f4cdca4434fdca141..a5d66bbd8f6dede1fda831961d6dcb9e98f3a8de 100644 (file)
@@ -1842,7 +1842,7 @@ extern inline int sx_set_serial_info(struct specialix_port * port,
        change_speed = ((port->flags & ASYNC_SPD_MASK) !=
                        (tmp.flags & ASYNC_SPD_MASK));
        
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((tmp.close_delay != port->close_delay) ||
                    (tmp.closing_wait != port->closing_wait) ||
                    ((tmp.flags & ~ASYNC_USR_MASK) !=
index 31fa5ab50029bbc26ea3d7865ef450845aa6d560..06795e07ab40965dc7e8114fdf32f54964b4d187 100644 (file)
@@ -1338,7 +1338,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct *sp)
 #endif
 
        copy_from_user(&sio, sp, sizeof(struct serial_struct));
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((sio.baud_base != portp->baud_base) ||
                    (sio.close_delay != portp->close_delay) ||
                    ((sio.flags & ~ASYNC_USR_MASK) !=
index 226f4a80b9356711c6f45b658172d7659446b8df..fd3002d0567661dbce77673af24f41e1b9947b66 100644 (file)
@@ -249,7 +249,8 @@ do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kb
                if (!(key_map = key_maps[s])) {
                        int j;
 
-                       if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
+                       if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && 
+                           !capable(CAP_SYS_RESOURCE))
                                return -EPERM;
 
                        key_map = (ushort *) kmalloc(sizeof(plain_map),
@@ -268,7 +269,7 @@ do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kb
                /*
                 * Attention Key.
                 */
-               if (((ov == K_SAK) || (v == K_SAK)) && !suser())
+               if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
                        return -EPERM;
                key_map[i] = U(v);
                if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
index 67c39c675de38237883941b1a2c5c55cfbddfc29..d94a8a77187005faecb3c2bd25f31121043cfd56 100644 (file)
@@ -384,7 +384,7 @@ static int capi_ioctl(struct inode *inode, struct file *file,
                        struct capi_manufacturer_cmd mcmd;
                        if (minor)
                                return -EINVAL;
-                       if (!suser())
+                       if (!capable(CAP_SYS_ADMIN))
                                return -EPERM;
                        retval = copy_from_user((void *) &mcmd, (void *) arg,
                                                sizeof(mcmd));
index 4232f5953ebd67e0ead098790733956b5593c1d3..9c3f18c9e17b9e27c9bb2ee0d96e279f8190dad0 100644 (file)
@@ -964,7 +964,7 @@ static int set_serial_info(struct mac_serial * info,
        copy_from_user(&new_serial,new_info,sizeof(new_serial));
        old_info = *info;
 
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((new_serial.baud_base != info->baud_base) ||
                    (new_serial.type != info->type) ||
                    (new_serial.close_delay != info->close_delay) ||
index 08860cc2795670222e22b7000d226183b31e09dd..523a1ca9436cd40a6865bee59e9034d76fec31a5 100644 (file)
@@ -6,20 +6,13 @@ Things to be done.
 
 2. A better lp.c:
 
-   a) It's a _mess_
-
-   b) ECP support would be nice.  This can only work if both the port and
+   a) ECP support would be nice.  This can only work if both the port and
       the printer support it.
 
-   c) Errors could do with being handled better.  There's no point logging a
-      message every 10 seconds when the printer is out of paper. 
-
-   d) Handle status readback automatically.  IEEE1284 printers can post status
+   b) Handle status readback automatically.  IEEE1284 printers can post status
       bits when they have something to say.  We should read out and deal 
       with (maybe just log) whatever the printer wants to tell the world.
 
 3. Support more hardware (eg m68k, Sun bpp).
 
 4. A better PLIP (make use of bidirectional/ECP/EPP ports).
-
-
index bb9ee3c30c78e34b3363731b0dd4e84c360fbaf8..ae344c99dcdb744446a507cac67c4af1090da15c 100644 (file)
@@ -1,8 +1,8 @@
 /* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
 /*
-       Written 1993-1995 by Donald Becker.
+       Written 1993-1997 by Donald Becker.
 
-       Copyright 1994,1995 by Donald Becker.
+       Copyright 1994-1997 by Donald Becker.
        Copyright 1993 United States Government as represented by the
        Director, National Security Agency.      This software may be used and
        distributed according to the terms of the GNU Public License,
        FIXES:
                Alan Cox:       Removed the 'Unexpected interrupt' bug.
                Michael Meskes: Upgraded to Donald Becker's version 1.07.
-               Phil Blundell:  Media selection support.
+               Alan Cox:       Increased the eeprom delay. Regardless of 
+                               what the docs say some people definitely
+                               get problems with lower (but in card spec)
+                               delays
+               v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
+                               other cleanups.  -djb
+               Andrea Arcangeli:       Upgraded to Donald Becker's version 1.12.
 */
 
-static char *version = "3c509.c:1.07 6/15/95 becker@cesdis.gsfc.nasa.gov\n";
+static char *version = "3c509.c:1.12 6/4/97 becker@cesdis.gsfc.nasa.gov\n";
+/* A few values that may be tweaked. */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (400*HZ/1000)
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+#define INTR_WORK      10
 
 #include <linux/module.h>
 
@@ -48,20 +60,19 @@ static char *version = "3c509.c:1.07 6/15/95 becker@cesdis.gsfc.nasa.gov\n";
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>       /* for udelay() */
-#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/io.h>
 
 #ifdef EL3_DEBUG
-static int el3_debug = EL3_DEBUG;
+int el3_debug = EL3_DEBUG;
 #else
-static int el3_debug = 2;
+int el3_debug = 2;
 #endif
 
 /* To minimize the size of the driver source I only define operating
    constants if they are used several times.  You'll need the manual
-   if you want to understand driver details. */
+   anyway if you want to understand driver details. */
 /* Offsets from base I/O address. */
 #define EL3_DATA 0x00
 #define EL3_CMD 0x0e
@@ -111,12 +122,14 @@ enum RxFilter {
 #define SKB_QUEUE_SIZE 64
 
 struct el3_private {
-       struct net_device_stats stats;
+       struct enet_statistics stats;
+       struct device *next_dev;
        /* skb send-queue */
        int head, size;
        struct sk_buff *queue[SKB_QUEUE_SIZE];
 };
 static int id_port = 0x100;
+static struct device *el3_root_dev = NULL;
 
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(short ioaddr, int index);
@@ -124,28 +137,19 @@ static int el3_open(struct device *dev);
 static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
 static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void update_stats(int addr, struct device *dev);
-static struct net_device_stats *el3_get_stats(struct device *dev);
+static struct enet_statistics *el3_get_stats(struct device *dev);
 static int el3_rx(struct device *dev);
 static int el3_close(struct device *dev);
-static int el3_set_config(struct device *dev, struct ifmap *map);
-#ifdef HAVE_MULTICAST
 static void set_multicast_list(struct device *dev);
-#endif
 
 \f
 
-__initfunc(int el3_probe(struct device *dev))
+int el3_probe(struct device *dev)
 {
        short lrs_state = 0xff, i;
-       ushort ioaddr, irq, port;
-       short *phys_addr = (short *)dev->dev_addr;
+       ushort ioaddr, irq, if_port;
+       short phys_addr[3];
        static int current_tag = 0;
-       static int el3_portmap[] = { 
-         IF_PORT_10BASET, 
-         IF_PORT_AUI, 
-         IF_PORT_UNKNOWN, 
-         IF_PORT_10BASE2 
-       };
 
        /* First check all slots of the EISA bus.  The next slot address to
           probe is kept in 'eisa_addr' to support multiple probe() calls. */
@@ -163,7 +167,7 @@ __initfunc(int el3_probe(struct device *dev))
                        outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
 
                        irq = inw(ioaddr + WN0_IRQ) >> 12;
-                       port = inw(ioaddr + 6)>>14;
+                       if_port = inw(ioaddr + 6)>>14;
                        for (i = 0; i < 3; i++)
                                phys_addr[i] = htons(read_eeprom(ioaddr, i));
 
@@ -175,18 +179,14 @@ __initfunc(int el3_probe(struct device *dev))
                }
        }
 
-/*
- * This has to be coded according to Documentation/mca.txt before
- * this driver can be used with the 3c529 MCA cards.
- */
-#if 0 /* #ifdef CONFIG_MCA */
+#ifdef CONFIG_MCA
        if (MCA_bus) {
                mca_adaptor_select_mode(1);
                for (i = 0; i < 8; i++)
                        if ((mca_adaptor_id(i) | 1) == 0x627c) {
                                ioaddr = mca_pos_base_addr(i);
                                irq = inw(ioaddr + WN0_IRQ) >> 12;
-                               port = inw(ioaddr + 6)>>14;
+                               if_port = inw(ioaddr + 6)>>14;
                                for (i = 0; i < 3; i++)
                                        phys_addr[i] = htons(read_eeprom(ioaddr, i));
 
@@ -203,6 +203,8 @@ __initfunc(int el3_probe(struct device *dev))
        outb(0x02, 0xA79);           /* Return to WaitForKey state. */
        /* Select an open I/O location at 0x1*0 to do contention select. */
        for (id_port = 0x100; id_port < 0x200; id_port += 0x10) {
+               if (check_region(id_port, 1))
+                       continue;
                outb(0x00, id_port);
                outb(0xff, id_port);
                if (inb(id_port) & 0x01)
@@ -218,13 +220,6 @@ __initfunc(int el3_probe(struct device *dev))
           on cards as they are found.  Cards with their tag set will not
           respond to subsequent ID sequences. */
 
-       if (check_region(id_port,1)) {
-         static int once = 1;
-         if (once) printk("3c509: Somebody has reserved 0x%x, can't do ID_PORT lookup, nor card auto-probing\n",id_port);
-          once = 0;
-          return -ENODEV;
-        }
-
        outb(0x00, id_port);
        outb(0x00, id_port);
        for(i = 0; i < 255; i++) {
@@ -252,16 +247,16 @@ __initfunc(int el3_probe(struct device *dev))
 
        {
                unsigned short iobase = id_read_eeprom(8);
-               port = iobase >> 14;
+               if_port = iobase >> 14;
                ioaddr = 0x200 + ((iobase & 0x1f) << 4);
        }
-       if (dev->irq > 1  &&  dev->irq < 16)
+       if (dev  &&  dev->irq > 1  &&  dev->irq < 16)
                irq = dev->irq;
        else
                irq = id_read_eeprom(9) >> 12;
 
-       if (dev->base_addr != 0
-               &&      dev->base_addr != (unsigned short)ioaddr) {
+       if (dev  &&  dev->base_addr != 0
+               &&  dev->base_addr != (unsigned short)ioaddr) {
                return -ENODEV;
        }
 
@@ -278,15 +273,20 @@ __initfunc(int el3_probe(struct device *dev))
        /* Free the interrupt so that some other card can use it. */
        outw(0x0f00, ioaddr + WN0_IRQ);
  found:
+       if (dev == NULL) {
+               dev = init_etherdev(dev, sizeof(struct el3_private));
+       }
+       memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr));
        dev->base_addr = ioaddr;
        dev->irq = irq;
-       dev->if_port = el3_portmap[port];
+       dev->if_port = (dev->mem_start & 0x1f) ? dev->mem_start & 3 : if_port;
+
        request_region(dev->base_addr, EL3_IO_EXTENT, "3c509");
 
        {
-               static const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
+               const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
                printk("%s: 3c509 at %#3.3lx tag %d, %s port, address ",
-                          dev->name, dev->base_addr, current_tag, if_names[port]);
+                          dev->name, dev->base_addr, current_tag, if_names[dev->if_port]);
        }
 
        /* Read in the station address. */
@@ -295,11 +295,15 @@ __initfunc(int el3_probe(struct device *dev))
        printk(", IRQ %d.\n", dev->irq);
 
        /* Make up a EL3-specific-data structure. */
-       dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
+       if (dev->priv == NULL)
+               dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
        if (dev->priv == NULL)
                return -ENOMEM;
        memset(dev->priv, 0, sizeof(struct el3_private));
 
+       ((struct el3_private *)dev->priv)->next_dev = el3_root_dev;
+       el3_root_dev = dev;
+
        if (el3_debug > 0)
                printk(version);
 
@@ -308,30 +312,26 @@ __initfunc(int el3_probe(struct device *dev))
        dev->hard_start_xmit = &el3_start_xmit;
        dev->stop = &el3_close;
        dev->get_stats = &el3_get_stats;
-       dev->set_config = &el3_set_config;
-#ifdef HAVE_MULTICAST
-               dev->set_multicast_list = &set_multicast_list;
-#endif
+       dev->set_multicast_list = &set_multicast_list;
 
        /* Fill in the generic fields of the device structure. */
        ether_setup(dev);
-       dev->flags |= IFF_PORTSEL;
        return 0;
 }
 
 /* Read a word from the EEPROM using the regular EEPROM access register.
    Assume that we are in register window zero.
  */
-__initfunc(static ushort read_eeprom(short ioaddr, int index))
+static ushort read_eeprom(short ioaddr, int index)
 {
        outw(EEPROM_READ + index, ioaddr + 10);
        /* Pause for at least 162 us. for the read to take place. */
-       udelay (300);
+       udelay (500);
        return inw(ioaddr + 12);
 }
 
 /* Read a word from the EEPROM when in the ISA ID probe state. */
-__initfunc(static ushort id_read_eeprom(int index))
+static ushort id_read_eeprom(int index)
 {
        int bit, word = 0;
 
@@ -340,8 +340,8 @@ __initfunc(static ushort id_read_eeprom(int index))
        outb(EEPROM_READ + index, id_port);
 
        /* Pause for at least 162 us. for the read to take place. */
-       udelay (300);
-
+       udelay (500);
+       
        for (bit = 15; bit >= 0; bit--)
                word = (word << 1) + (inb(id_port) & 0x01);
 
@@ -352,59 +352,6 @@ __initfunc(static ushort id_read_eeprom(int index))
 }
 
 
-\f
-static int
-el3_set_config(struct device *dev, struct ifmap *map)
-{
-       int ioaddr = dev->base_addr;
-    if (map->port != dev->if_port) {
-         switch (map->port) {
-         case IF_PORT_10BASE2:
-         case IF_PORT_10BASET:
-         case IF_PORT_AUI:
-               if (dev->start) {
-                 if (dev->if_port == IF_PORT_10BASE2)
-                       /* Turn off thinnet power. */
-                       outw(StopCoax, ioaddr + EL3_CMD);
-                 else if (dev->if_port == IF_PORT_10BASET) {
-                       /* Disable link beat and jabber */
-                       EL3WINDOW(4);
-                       outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
-                       EL3WINDOW(1);
-                 }
-               }
-               printk(KERN_INFO "%s: %s port selected.\n", dev->name, 
-                          if_port_text[map->port]);
-               dev->if_port = map->port;
-               if (dev->start) {
-                 if (dev->if_port == IF_PORT_10BASE2)
-                       /* Start the thinnet transceiver. We should really wait 50ms...*/
-                       outw(StartCoax, ioaddr + EL3_CMD);
-                 else if (dev->if_port == IF_PORT_10BASET) {
-                       /* 10baseT interface, enabled link beat and jabber check. */
-                       EL3WINDOW(4);
-                       outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
-                       EL3WINDOW(1);
-                 }
-               }
-               break;
-         default:
-               printk(KERN_ERR "%s: %s port not supported.\n", dev->name, 
-                          if_port_text[map->port]);
-               return -EINVAL;
-         }
-       }
-       if (map->irq != dev->irq) {
-         printk(KERN_ERR "%s: cannot change interrupt.\n", dev->name);
-         return -EINVAL;
-       }
-       if (map->base_addr != dev->base_addr) {
-         printk(KERN_ERR "%s: cannot change base address.\n", dev->name);
-         return -EINVAL;
-       }
-       return 0;
-}
-
 \f
 static int
 el3_open(struct device *dev)
@@ -437,10 +384,10 @@ el3_open(struct device *dev)
        for (i = 0; i < 6; i++)
                outb(dev->dev_addr[i], ioaddr + i);
 
-       if (dev->if_port == IF_PORT_10BASE2)
+       if (dev->if_port == 3)
                /* Start the thinnet transceiver. We should really wait 50ms...*/
                outw(StartCoax, ioaddr + EL3_CMD);
-       else if (dev->if_port == IF_PORT_10BASET) {
+       else if (dev->if_port == 0) {
                /* 10baseT interface, enabled link beat and jabber check. */
                EL3WINDOW(4);
                outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
@@ -483,7 +430,8 @@ el3_open(struct device *dev)
        return 0;                                       /* Always succeed */
 }
 
-static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
+static int
+el3_start_xmit(struct sk_buff *skb, struct device *dev)
 {
        struct el3_private *lp = (struct el3_private *)dev->priv;
        int ioaddr = dev->base_addr;
@@ -491,7 +439,7 @@ static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
        /* Transmitter timeout, serious problems. */
        if (dev->tbusy) {
                int tickssofar = jiffies - dev->trans_start;
-               if (tickssofar < 40*HZ/100)
+               if (tickssofar < TX_TIMEOUT)
                        return 1;
                printk("%s: transmit timed out, Tx_status %2.2x status %4.4x "
                           "Tx FIFO room %d.\n",
@@ -532,12 +480,15 @@ static int el3_start_xmit(struct sk_buff *skb, struct device *dev)
        if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
                printk("%s: Transmitter access conflict.\n", dev->name);
        else {
-               lp->stats.tx_bytes+=skb->len;
                /* Put out the doubleword header... */
                outw(skb->len, ioaddr + TX_FIFO);
                outw(0x00, ioaddr + TX_FIFO);
                /* ... and the packet rounded to a doubleword. */
+#ifdef  __powerpc__
+               outsl_unswapped(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+#else
                outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
+#endif
 
                dev->trans_start = jiffies;
                if (inw(ioaddr + TX_FREE) > 1536) {
@@ -570,7 +521,7 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
        struct device *dev = (struct device *)dev_id;
        int ioaddr, status;
-       int i = 0;
+       int i = INTR_WORK;
 
        if (dev == NULL) {
                printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
@@ -622,7 +573,7 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                        }
                }
 
-               if (++i > 10) {
+               if (--i < 0) {
                        printk("%s: Infinite loop in interrupt, status %4.4x.\n",
                                   dev->name, status);
                        /* Clear all interrupts. */
@@ -643,7 +594,8 @@ el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 
-static struct net_device_stats *el3_get_stats(struct device *dev)
+static struct enet_statistics *
+el3_get_stats(struct device *dev)
 {
        struct el3_private *lp = (struct el3_private *)dev->priv;
        unsigned long flags;
@@ -720,18 +672,21 @@ el3_rx(struct device *dev)
                                           pkt_len, rx_status);
                        if (skb != NULL) {
                                skb->dev = dev;
-                               skb_reserve(skb,2);     /* Align IP on 16 byte */
+                               skb_reserve(skb, 2);     /* Align IP on 16 byte */
 
                                /* 'skb->data' points to the start of sk_buff data area. */
-                               insl(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
-                                                       (pkt_len + 3) >> 2);
+#ifdef  __powerpc__
+                               insl_unswapped(ioaddr+RX_FIFO, skb_put(skb,pkt_len),
+                                                          (pkt_len + 3) >> 2);
+#else
+                               insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
+                                        (pkt_len + 3) >> 2);
+#endif
 
-                               skb->protocol=eth_type_trans(skb,dev);
+                               skb->protocol = eth_type_trans(skb,dev);
                                netif_rx(skb);
                                outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
-                               lp->stats.rx_bytes+=skb->len;
                                lp->stats.rx_packets++;
-                               lp->stats.rx_bytes+=pkt_len;
                                continue;
                        } else if (el3_debug)
                                printk("%s: Couldn't allocate a sk_buff of size %d.\n",
@@ -747,7 +702,6 @@ el3_rx(struct device *dev)
        return 0;
 }
 
-#ifdef HAVE_MULTICAST
 /*
  *     Set or clear the multicast filter for this adaptor.
  */
@@ -772,7 +726,6 @@ set_multicast_list(struct device *dev)
        else
                 outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
 }
-#endif
 
 static int
 el3_close(struct device *dev)
@@ -792,10 +745,10 @@ el3_close(struct device *dev)
        outw(RxDisable, ioaddr + EL3_CMD);
        outw(TxDisable, ioaddr + EL3_CMD);
 
-       if (dev->if_port == IF_PORT_10BASE2)
+       if (dev->if_port == 3)
                /* Turn off thinnet power.  Green! */
                outw(StopCoax, ioaddr + EL3_CMD);
-       else if (dev->if_port == IF_PORT_10BASET) {
+       else if (dev->if_port == 0) {
                /* Disable link beat and jabber, if_port may change ere next open(). */
                EL3WINDOW(4);
                outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
@@ -813,69 +766,50 @@ el3_close(struct device *dev)
 }
 
 #ifdef MODULE
-#define MAX_3C_CARDS   4       /* Max number of NE cards per module */
-#define NAMELEN                8       /* # of chars for storing dev->name */
-static char namelist[NAMELEN * MAX_3C_CARDS] = { 0, };
-static struct device dev_3c509[MAX_3C_CARDS] = {
-       {
-               NULL,           /* assign a chunk of namelist[] below */
-               0, 0, 0, 0,
-               0, 0,
-               0, 0, 0, NULL, NULL
-       },
-};
-
-static int io[MAX_3C_CARDS] = { 0, };
-static int irq[MAX_3C_CARDS]  = { 0, };
-MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C_CARDS) "i");
-MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C_CARDS) "i");
+/* Parameter that may be passed into the module. */
+static int debug = -1;
+static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int xcvr[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
 int
 init_module(void)
 {
-       int this_dev, found = 0;
-
-       for (this_dev = 0; this_dev < MAX_3C_CARDS; this_dev++) {
-               struct device *dev = &dev_3c509[this_dev];
-               dev->name = namelist+(NAMELEN*this_dev);
-               dev->irq = irq[this_dev];
-               dev->base_addr = io[this_dev];
-               dev->init = el3_probe;
-               if (io[this_dev] == 0)  {
-                       if (this_dev != 0) break; /* only complain once */
-                       printk("3c509: WARNING! Module load-time probing works reliably only for EISA bus!!\n");
-               }
-               if (register_netdev(dev) != 0) {
-                       printk(KERN_WARNING "3c509.c: No 3c509 card found (i/o = 0x%x).\n", io[this_dev]);
-                       if (found != 0) return 0;       /* Got at least one. */
-                       return -ENXIO;
-               }
-               found++;
+       int el3_cards = 0;
+
+       if (debug >= 0)
+               el3_debug = debug;
+
+       el3_root_dev = NULL;
+       while (el3_probe(0) == 0) {
+               if (irq[el3_cards] > 1)
+                       el3_root_dev->irq = irq[el3_cards];
+               if (xcvr[el3_cards] >= 0)
+                       el3_root_dev->if_port = xcvr[el3_cards];
+               el3_cards++;
        }
-       return 0;
+
+       return el3_cards ? 0 : -ENODEV;
 }
 
 void
 cleanup_module(void)
 {
-       int this_dev;
-
-       for (this_dev = 0; this_dev < MAX_3C_CARDS; this_dev++) {
-               struct device *dev = &dev_3c509[this_dev];
-               if (dev->priv != NULL) {
-                       unregister_netdev(dev);
-                       kfree_s(dev->priv,sizeof(struct el3_private));
-                       dev->priv = NULL;
-                       free_irq(dev->irq, dev);
-                       release_region(dev->base_addr, EL3_IO_EXTENT);
-               }
+       struct device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (el3_root_dev) {
+               next_dev = ((struct el3_private *)el3_root_dev->priv)->next_dev;
+               unregister_netdev(el3_root_dev);
+               release_region(el3_root_dev->base_addr, EL3_IO_EXTENT);
+               kfree(el3_root_dev);
+               el3_root_dev = next_dev;
        }
 }
 #endif /* MODULE */
 \f
 /*
  * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 3c509.c"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c509.c"
  *  version-control: t
  *  kept-new-versions: 5
  *  tab-width: 4
index a9ddfa4752208d45bef89bd963ebf264c97ed5ec..6bb3dfd54e834ec78938c9acde8917d54d4ba2ab 100644 (file)
@@ -1957,7 +1957,7 @@ static int vortex_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
                return 0;
index c0c52d24fb1462716b206aaefc4ca64fc5c2e424..06f527d7072b606c118f453ae0467b7435835f57 100644 (file)
@@ -5487,7 +5487,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        if (status)
          break;
        status = -EPERM;
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
          break;
        status = 0;
        copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
@@ -5505,7 +5505,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
       case DE4X5_SET_PROM:             /* Set Promiscuous Mode */
-       if (suser()) {
+       if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr |= OMR_PR;
            outl(omr, DE4X5_OMR);
@@ -5516,7 +5516,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
       case DE4X5_CLR_PROM:             /* Clear Promiscuous Mode */
-       if (suser()) {
+       if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr &= ~OMR_PR;
            outb(omr, DE4X5_OMR);
@@ -5531,7 +5531,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
       case DE4X5_MCA_EN:               /* Enable pass all multicast addressing */
-       if (suser()) {
+       if (capable(CAP_NET_ADMIN)) {
            omr = inl(DE4X5_OMR);
            omr |= OMR_PM;
            outl(omr, DE4X5_OMR);
@@ -5552,7 +5552,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
       case DE4X5_CLR_STATS:            /* Zero out the driver statistics */
-       if (suser()) {
+       if (capable(CAP_NET_ADMIN)) {
            cli();
            memset(&lp->pktStats, 0, sizeof(lp->pktStats));
            sti();
@@ -5569,7 +5569,7 @@ de4x5_ioctl(struct device *dev, struct ifreq *rq, int cmd)
        
        break;
       case DE4X5_SET_OMR:              /* Set the OMR Register contents */
-       if (suser()) {
+       if (capable(CAP_NET_ADMIN)) {
            if (!(status = verify_area(VERIFY_READ, (void *)ioc->data, 1))) {
                copy_from_user(tmp.addr, ioc->data, 1);
                outl(tmp.addr[0], DE4X5_OMR);
index 56578f58ead0d06c5367d32a9c4fb11ad98bb9da..0320cc3223656000ed1aac531724cae864604c82 100644 (file)
@@ -1714,7 +1714,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                break;
        case DEPCA_SET_HWADDR:  /* Set the hardware address */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
                                copy_from_user(tmp.addr, ioc->data, ETH_ALEN);
                                for (i = 0; i < ETH_ALEN; i++) {
@@ -1736,7 +1736,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case DEPCA_SET_PROM:    /* Set Promiscuous Mode */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        while (dev->tbusy);     /* Stop ring access */
                        set_bit(0, (void *) &dev->tbusy);
                        while (lp->tx_old != lp->tx_new);       /* Wait for the ring to empty */
@@ -1754,7 +1754,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case DEPCA_CLR_PROM:    /* Clear Promiscuous Mode */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        while (dev->tbusy);     /* Stop ring access */
                        set_bit(0, (void *) &dev->tbusy);
                        while (lp->tx_old != lp->tx_new);       /* Wait for the ring to empty */
@@ -1782,7 +1782,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                break;
        case DEPCA_SET_MCA:     /* Set a multicast address */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
                                copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
                                set_multicast_list(dev);
@@ -1793,7 +1793,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case DEPCA_CLR_MCA:     /* Clear all multicast addresses */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        set_multicast_list(dev);
                } else {
                        status = -EPERM;
@@ -1801,7 +1801,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case DEPCA_MCA_EN:      /* Enable pass all multicast addressing */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        set_multicast_list(dev);
                } else {
                        status = -EPERM;
@@ -1818,7 +1818,7 @@ static int depca_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case DEPCA_CLR_STATS:   /* Zero out the driver statistics */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        cli();
                        memset(&lp->pktStats, 0, sizeof(lp->pktStats));
                        sti();
index 8ceb7a8c7ad7fd16d63e97bb600d64d769f423f4..6343463d0de285c7edc7944426ad491cab2a4312 100644 (file)
@@ -322,7 +322,7 @@ int dlci_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
 {
        struct dlci_local *dlp;
 
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
                return(-EPERM);
 
        dlp = dev->priv;
@@ -542,7 +542,7 @@ int dlci_ioctl(unsigned int cmd, void *arg)
        struct dlci_add add;
        int err;
        
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
                return(-EPERM);
 
        if(copy_from_user(&add, arg, sizeof(struct dlci_add)))
index c896844b2e823a1de868fd4cbb54481deab3bf3c..cc23deba7e5534b3a5599c6b1c8bc5f11659558c 100644 (file)
@@ -1528,7 +1528,7 @@ static int speedo_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                data[3] = mdio_read(ioaddr, data[0], data[1]);
                return 0;
        case SIOCDEVPRIVATE+2:          /* Write the specified MII register */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                mdio_write(ioaddr, data[0], data[1], data[2]);
                return 0;
index f654b2cdd0961cdbcb0fae7c73c42ba2c14f6286..abb7e6c785ad63df407acc6bcdf2afd58ff292e6 100644 (file)
@@ -329,7 +329,8 @@ static int eql_close(struct device *dev)
 
 static int eql_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
 {  
-       if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && !suser())
+       if(cmd!=EQL_GETMASTRCFG && cmd!=EQL_GETSLAVECFG && 
+          !capable(CAP_NET_ADMIN))
                return -EPERM;
        switch (cmd)
        {
index f17343b409cae3ba639c443b08f06313eab6b4e9..315cc27daac781a21c0e1dc1879051ee4853fcb2 100644 (file)
@@ -1684,7 +1684,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                break;
        case EWRK3_SET_HWADDR:  /* Set the hardware address */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, (void *) ioc->data, ETH_ALEN))) {
                                csr = inb(EWRK3_CSR);
                                csr |= (CSR_TXD | CSR_RXD);
@@ -1705,7 +1705,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_SET_PROM:    /* Set Promiscuous Mode */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        csr = inb(EWRK3_CSR);
                        csr |= CSR_PME;
                        csr &= ~CSR_MCE;
@@ -1716,7 +1716,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_CLR_PROM:    /* Clear Promiscuous Mode */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        csr = inb(EWRK3_CSR);
                        csr &= ~CSR_PME;
                        outb(csr, EWRK3_CSR);
@@ -1749,7 +1749,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_SET_MCA:     /* Set a multicast address */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, ioc->data, ETH_ALEN * ioc->len))) {
                                copy_from_user(tmp.addr, ioc->data, ETH_ALEN * ioc->len);
                                set_multicast_list(dev);
@@ -1760,7 +1760,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_CLR_MCA:     /* Clear all multicast addresses */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        set_multicast_list(dev);
                } else {
                        status = -EPERM;
@@ -1768,7 +1768,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_MCA_EN:      /* Enable multicast addressing */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        csr = inb(EWRK3_CSR);
                        csr |= CSR_MCE;
                        csr &= ~CSR_PME;
@@ -1788,7 +1788,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_CLR_STATS:   /* Zero out the driver statistics */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        cli();
                        memset(&lp->pktStats, 0, sizeof(lp->pktStats));
                        sti();
@@ -1805,7 +1805,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
                }
                break;
        case EWRK3_SET_CSR:     /* Set the CSR Register contents */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, ioc->data, 1))) {
                                copy_from_user(tmp.addr, ioc->data, 1);
                                outb(tmp.addr[0], EWRK3_CSR);
@@ -1816,7 +1816,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_GET_EEPROM:  /* Get the EEPROM contents */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        for (i = 0; i < (EEPROM_MAX >> 1); i++) {
                                tmp.val[i] = (short) Read_EEPROM(iobase, i);
                        }
@@ -1835,7 +1835,7 @@ static int ewrk3_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 
                break;
        case EWRK3_SET_EEPROM:  /* Set the EEPROM contents */
-               if (suser()) {
+               if (capable(CAP_NET_ADMIN)) {
                        if (!(status = verify_area(VERIFY_READ, ioc->data, EEPROM_MAX))) {
                                copy_from_user(tmp.addr, ioc->data, EEPROM_MAX);
                                for (i = 0; i < (EEPROM_MAX >> 1); i++) {
index 16e52bd98ff504a0e001c75ed6a1cbd9cf150493..df22a0ee7fcfc937cd0e04878f0f7090d92d501a 100644 (file)
@@ -307,7 +307,7 @@ static int ipddp_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
 {
         struct ipddp_route *rt = (struct ipddp_route *)ifr->ifr_data;
 
-        if(!suser())
+        if(!capable(CAP_NET_ADMIN))
                 return -EPERM;
 
         switch(cmd)
index 9dd39b7b3543db7c114be1a9254790f9a4914da3..9d4a237c7348d665d010d91c40d51ef874e01d46 100644 (file)
@@ -2281,7 +2281,7 @@ ppp_tty_ioctl (struct tty_struct *tty, struct file * file,
 /*
  * The user must have an euid of root to do these requests.
  */
-       if (!suser ())
+       if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 /*
  * Set the MRU value
index 7424a20d402d76edd04f6285991125dcecbafb27..3e15ce47db4f6ee0e0a30da02f331e8ea7a8f81a 100644 (file)
@@ -57,7 +57,7 @@ proc_bus_pci_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
         * undefined locations (think of Intel PIIX4 as a typical example).
         */
 
-       if (fsuser())
+       if (capable(CAP_SYS_ADMIN))
                size = PCI_CFG_SPACE_SIZE;
        else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
                size = 128;
index ccc8dd2cd5813e79c05a8ff073bc8da15330eb42..160c7e5de7cf9aeb6b7f7a5ca3a335b6b54e82bd 100644 (file)
@@ -91,7 +91,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 
        case RTCSET:
-               if (!suser())
+               if (!capable(CAP_SYS_TIME))
                        return -EPERM;
 
                copy_from_user_ret(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time), -EFAULT);
index cb822dd2a30d46a33f5396c8cf5891be9367d546..81a8b7477e57b00923b61827c3e620455d6a6b67 100644 (file)
@@ -205,7 +205,7 @@ static int vfc_debug(struct vfc_dev *dev, int cmd, unsigned long arg)
        unsigned char *buffer;
        int ret;
 
-       if(!suser()) return -EPERM;
+       if(!capable(CAP_SYS_ADMIN)) return -EPERM;
 
        switch(cmd) {
        case VFC_I2C_SEND:
index f7c477ea4b708f490437798af6a83c8be9fbc3c6..3d8d24a02cba0b994bf9a4b07069a8bf5fe30f35 100644 (file)
@@ -1265,7 +1265,7 @@ static int set_serial_info(struct sun_serial * info,
                return -EFAULT;
        old_info = *info;
 
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((new_serial.baud_base != info->baud_base) ||
                    (new_serial.type != info->type) ||
                    (new_serial.close_delay != info->close_delay) ||
index cc05c37864e428eaa6f9d8d98f25c6a3fab5cc3d..05c0ecab9f2b2395f79b4f827c3401c7a8787615 100644 (file)
@@ -327,7 +327,7 @@ static void idescsi_pc_intr (ide_drive_t *drive)
        if ((status & DRQ_STAT) == 0) {                                 /* No more interrupts */
                if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
                        printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-               ide_sti();
+               ide__sti();
                if (status & ERR_STAT)
                        rq->errors++;
                idescsi_end_request (1, HWGROUP(drive));
index ebdcb560c637e3f1ee72848dc4ce345d5bcbd5d3..5e67230e36bffba5a9336a10694f2385fd139ac9 100644 (file)
@@ -50,13 +50,6 @@ NULL,                /* cur_cmd */   \
 #include  "ppa.h"
 #include <linux/parport.h>
 
-#ifdef CONFIG_KMOD
-#include  <linux/kmod.h>
-#ifndef PARPORT_MODULES
-#define PARPORT_MODULES "parport_pc"
-#endif
-#endif
-
 #define NO_HOSTS 4
 static ppa_struct ppa_hosts[NO_HOSTS] =
 {PPA_EMPTY, PPA_EMPTY, PPA_EMPTY, PPA_EMPTY};
@@ -98,7 +91,6 @@ static int ppa_pb_claim(int host_no)
        return 1;
     }
 
-    PPA_BASE(host_no) = ppa_hosts[host_no].dev->port->base;
     if (ppa_hosts[host_no].cur_cmd)
        ppa_hosts[host_no].cur_cmd->SCp.phase++;
     return 0;
@@ -130,12 +122,8 @@ int ppa_detect(Scsi_Host_Template * host)
     nhosts = 0;
     try_again = 0;
 
-#ifdef CONFIG_KMOD
-    if (!pb) {
-       request_module(PARPORT_MODULES);
+    if (!pb)
        pb = parport_enumerate();
-    }
-#endif
 
     if (!pb) {
        printk("ppa: parport reports no devices.\n");
@@ -155,7 +143,7 @@ int ppa_detect(Scsi_Host_Template * host)
        if (ppa_pb_claim(i))
            while (ppa_hosts[i].p_busy)
                schedule(); /* Whe can safe schedule() here */
-       ppb = PPA_BASE(i);
+       ppb = PPA_BASE(i) = ppa_hosts[i].dev->port->base;
        w_ctr(ppb, 0x0c);
        modes = ppa_hosts[i].dev->port->modes;
 
index e2f933fb3c5d087851e9d4b9d578a29d482e6a59..b5692acd1a0f767d9b00018f00e359719ef17f57 100644 (file)
@@ -379,13 +379,13 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
         put_user( dev->host->host_no, (int *) arg);
        return 0;
     case SCSI_IOCTL_TAGGED_ENABLE:
-       if(!suser())  return -EACCES;
+       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
        if(!dev->tagged_supported) return -EINVAL;
        dev->tagged_queue = 1;
        dev->current_tag = 1;
        return 0;
     case SCSI_IOCTL_TAGGED_DISABLE:
-       if(!suser())  return -EACCES;
+       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
        if(!dev->tagged_supported) return -EINVAL;
        dev->tagged_queue = 0;
        dev->current_tag = 0;
@@ -393,7 +393,7 @@ int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg)
     case SCSI_IOCTL_PROBE_HOST:
        return ioctl_probe(dev->host, arg);
     case SCSI_IOCTL_SEND_COMMAND:
-       if(!suser())  return -EACCES;
+       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
        return scsi_ioctl_send_command((Scsi_Device *) dev,
                                       (Scsi_Ioctl_Command *) arg);
     case SCSI_IOCTL_DOORLOCK:
index 2f771552a17ca77dd7caef022461dec4aa13962f..a29d958d1d17035bc410ea7c2a4b688a6e737779 100644 (file)
@@ -79,7 +79,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        return 0;
 
     case BLKRASET:
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if(!(inode->i_rdev)) return -EINVAL;
        if(arg > 0xff) return -EINVAL;
@@ -96,13 +96,15 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
        return 0;
 
     case BLKFLSBUF:
-       if(!suser())  return -EACCES;
+       if(!capable(CAP_SYS_ADMIN))  return -EACCES;
        if(!(inode->i_rdev)) return -EINVAL;
        fsync_dev(inode->i_rdev);
        invalidate_buffers(inode->i_rdev);
        return 0;
        
     case BLKRRPART: /* Re-read partition tables */
+        if (!capable(CAP_SYS_ADMIN))
+                return -EACCES;
        return revalidate_scsidisk(dev, 1);
 
     RO_IOCTLS(dev, arg);
index 59e135bb3522bece9c9015002429a3ce706a4b72..1d34cf7ec383203d5a3360b63c2fbcdbe4fd259c 100644 (file)
@@ -792,7 +792,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
        return 0;
 
     case BLKRASET:
-       if(!suser())
+       if(!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if(!(cdi->dev))
                return -EINVAL;
@@ -804,7 +804,7 @@ int sr_dev_ioctl(struct cdrom_device_info *cdi,
     RO_IOCTLS(cdi->dev,arg);
 
     case BLKFLSBUF:
-       if(!suser())
+       if(!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if(!(cdi->dev))
                return -EINVAL;
index 35af3e391718b2201fd06ef14642a38312e74cbc..a0adf83b33bfc6f46114bec9fe61627e08980b53 100644 (file)
@@ -2831,7 +2831,7 @@ st_ioctl(struct inode * inode,struct file * file,
      if (i)
         return (-EFAULT);
 
-     if (mtc.mt_op == MTSETDRVBUFFER && !suser()) {
+     if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) {
        printk(KERN_WARNING "st%d: MTSETDRVBUFFER only allowed for root.\n", dev);
        return (-EPERM);
      }
index 79feefb294ddb98609958ad5972d3e01fe232514..8328b14e1c4b8b8114350379fa1ab810bb9e1be5 100644 (file)
@@ -1201,7 +1201,7 @@ static int set_serial_info(struct sgi_serial * info,
        copy_from_user(&new_serial,new_info,sizeof(new_serial));
        old_info = *info;
 
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                if ((new_serial.baud_base != info->baud_base) ||
                    (new_serial.type != info->type) ||
                    (new_serial.close_delay != info->close_delay) ||
index 96d8c6f5a946567fb4c3fe0e69151dc1a0291f43..d6480b4ee0d1f241088c6482fa0efda23b8f3a6c 100644 (file)
@@ -245,7 +245,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
        if (S_ISDIR(inode->i_mode))
                goto unlink_done;
        if (current->fsuid != inode->i_uid &&
-           current->fsuid != dir->i_uid && !fsuser())
+           current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto unlink_done;
 
        if ((retval = affs_remove_header(bh,inode)) < 0)
@@ -363,7 +363,7 @@ affs_rmdir(struct inode *dir, struct dentry *dentry)
 
        retval = -EPERM;
         if (current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !fsuser())
+            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto rmdir_done;
        if (inode->i_dev != dir->i_dev)
                goto rmdir_done;
index e916a2a3d115c30a283b052245dc2532f472886e..789713164274ca82463bd8de163fe0a1239774ba 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -27,28 +27,28 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
        /* Make sure a caller can chown. */
        if ((ia_valid & ATTR_UID) &&
            (current->fsuid != inode->i_uid ||
-            attr->ia_uid != inode->i_uid) && !fsuser())
+            attr->ia_uid != inode->i_uid) && !capable(CAP_CHOWN))
                goto error;
 
        /* Make sure caller can chgrp. */
        if ((ia_valid & ATTR_GID) &&
            (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid) &&
-           !fsuser())
+           !capable(CAP_CHOWN))
                goto error;
 
        /* Make sure a caller can chmod. */
        if (ia_valid & ATTR_MODE) {
-               if ((current->fsuid != inode->i_uid) && !fsuser())
+               if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        goto error;
                /* Also check the setgid bit! */
                if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid :
-                               inode->i_gid) && !fsuser())
+                               inode->i_gid) && !capable(CAP_FSETID))
                        attr->ia_mode &= ~S_ISGID;
        }
 
        /* Check for setting the inode time. */
        if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) {
-               if (current->fsuid != inode->i_uid && !fsuser())
+               if (current->fsuid != inode->i_uid && !capable(CAP_FOWNER))
                        goto error;
        }
 fine:
@@ -75,7 +75,7 @@ void inode_setattr(struct inode * inode, struct iattr * attr)
                inode->i_ctime = attr->ia_ctime;
        if (ia_valid & ATTR_MODE) {
                inode->i_mode = attr->ia_mode;
-               if (!in_group_p(inode->i_gid) && !fsuser())
+               if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
                        inode->i_mode &= ~S_ISGID;
        }
        mark_inode_dirty(inode);
index 60f9efe0109c554c38b6d0d295f8f40e2d9464b9..2eec54de4ac742331390a06d966d3bac4a9b0958 100644 (file)
@@ -478,7 +478,7 @@ static int autofs_root_ioctl(struct inode *inode, struct file *filp,
             _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
                return -ENOTTY;
        
-       if ( !autofs_oz_mode(sbi) && !fsuser() )
+       if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
                return -EPERM;
        
        switch(cmd) {
index 5e55f89c74c072f4b75b03d35bd2c1fdc7eef2e0..887b9255c089374e1f194408649cbbb9b75c4af1 100644 (file)
@@ -1871,7 +1871,7 @@ asmlinkage int sys_bdflush(int func, long data)
        int i, error = -EPERM;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                goto out;
 
        if (func == 1) {
index b868ac3d7b747c874baf13dfab43774764f3327f..58393b016945aaf70d378a199eea7baaaefa5544 100644 (file)
@@ -375,7 +375,8 @@ static int check_idq(struct dquot *dquot, short type, u_long short inodes)
        if (inodes <= 0 || dquot->dq_flags & DQ_FAKE)
                return(QUOTA_OK);
        if (dquot->dq_ihardlimit &&
-          (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && !fsuser()) {
+          (dquot->dq_curinodes + inodes) > dquot->dq_ihardlimit && 
+           !capable(CAP_SYS_RESOURCE)) {
                if ((dquot->dq_flags & DQ_INODES) == 0 &&
                      need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: write failed, %s file limit reached\r\n",
@@ -387,7 +388,8 @@ static int check_idq(struct dquot *dquot, short type, u_long short inodes)
        }
        if (dquot->dq_isoftlimit &&
           (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
-           dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && !fsuser()) {
+           dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime && 
+           !capable(CAP_SYS_RESOURCE)) {
                 if (need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: warning, %s file quota exceeded too long.\r\n",
                                dquot->dq_mnt->mnt_dirname, quotatypes[type]);
@@ -397,7 +399,8 @@ static int check_idq(struct dquot *dquot, short type, u_long short inodes)
        }
        if (dquot->dq_isoftlimit &&
           (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
-           dquot->dq_itime == 0 && !fsuser()) {
+           dquot->dq_itime == 0 && 
+           !capable(CAP_SYS_RESOURCE)) {
                 if (need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: warning, %s file quota exceeded\r\n",
                                dquot->dq_mnt->mnt_dirname, quotatypes[type]);
@@ -413,7 +416,8 @@ static int check_bdq(struct dquot *dquot, short type, u_long blocks)
        if (blocks <= 0 || dquot->dq_flags & DQ_FAKE)
                return(QUOTA_OK);
        if (dquot->dq_bhardlimit &&
-          (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && !fsuser()) {
+          (dquot->dq_curblocks + blocks) > dquot->dq_bhardlimit && 
+           !capable(CAP_SYS_RESOURCE)) {
                if ((dquot->dq_flags & DQ_BLKS) == 0 &&
                      need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: write failed, %s disk limit reached.\r\n",
@@ -425,7 +429,8 @@ static int check_bdq(struct dquot *dquot, short type, u_long blocks)
        }
        if (dquot->dq_bsoftlimit &&
           (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
-           dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && !fsuser()) {
+           dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime && 
+           !capable(CAP_SYS_RESOURCE)) {
                 if (need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: write failed, %s disk quota exceeded too long.\r\n",
                                dquot->dq_mnt->mnt_dirname, quotatypes[type]);
@@ -435,7 +440,8 @@ static int check_bdq(struct dquot *dquot, short type, u_long blocks)
        }
        if (dquot->dq_bsoftlimit &&
           (dquot->dq_curblocks + blocks) > dquot->dq_bsoftlimit &&
-           dquot->dq_btime == 0 && !fsuser()) {
+           dquot->dq_btime == 0 && 
+           !capable(CAP_SYS_RESOURCE)) {
                 if (need_print_warning(type, dquot)) {
                        sprintf(quotamessage, "%s: warning, %s disk quota exceeded\r\n",
                                dquot->dq_mnt->mnt_dirname, quotatypes[type]);
@@ -1039,11 +1045,12 @@ asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
                        break;
                case Q_GETQUOTA:
                        if (((type == USRQUOTA && current->uid != id) ||
-                            (type == GRPQUOTA && in_group_p(id))) && !fsuser())
+                            (type == GRPQUOTA && in_group_p(id))) && 
+                           !capable(CAP_SYS_ADMIN))
                                goto out;
                        break;
                default:
-                       if (!fsuser())
+                       if (!capable(CAP_SYS_ADMIN))
                                goto out;
        }
 
index 6a054ecdde26bfc1ce2578e2d7458f885a7bec5d..7defb07e3f1c3e7c300ce3ceed66e9234bce4644 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -419,6 +419,7 @@ static int exec_mmap(void)
        retval = new_page_tables(current);
        if (retval)
                goto fail_restore;
+       activate_context(current);
        up(&mm->mmap_sem);
        mmput(old_mm);
        return 0;
@@ -564,7 +565,7 @@ flush_failed:
 int prepare_binprm(struct linux_binprm *bprm)
 {
        int mode;
-       int retval,id_change;
+       int retval,id_change,cap_raised;
        struct inode * inode = bprm->dentry->d_inode;
 
        mode = inode->i_mode;
@@ -584,7 +585,7 @@ int prepare_binprm(struct linux_binprm *bprm)
 
        bprm->e_uid = current->euid;
        bprm->e_gid = current->egid;
-       id_change = 0;
+       id_change = cap_raised = 0;
 
        /* Set-uid? */
        if (mode & S_ISUID) {
@@ -630,21 +631,25 @@ int prepare_binprm(struct linux_binprm *bprm)
                        cap_set_full(bprm->cap_effective);
        }
 
-        /* We use a conservative definition of suid for capabilities.
-         * The process is suid if the permitted set is not a subset of
-         * the current permitted set after the exec call.
-         *         new permitted set = forced | (allowed & inherited)
-         *                       pP' = fP     | (fI      & pI)
-         */
-
-        if ((bprm->cap_permitted.cap |
-            (current->cap_inheritable.cap &
-             bprm->cap_inheritable.cap)) &
-           ~current->cap_permitted.cap) {
-               id_change = 1;
+        /* Only if pP' is _not_ a subset of pP, do we consider there
+         * has been a capability related "change of capability".  In
+         * such cases, we need to check that the elevation of
+         * privilege does not go against other system constraints.
+         * The new Permitted set is defined below -- see (***). */
+       {
+               kernel_cap_t working =
+                       cap_combine(bprm->cap_permitted,
+                                   cap_intersect(bprm->cap_inheritable,
+                                                 current->cap_inheritable));
+               if (!cap_issubset(working, current->cap_permitted)) {
+                       cap_raised = 1;
+               }
        }
 
-       if (id_change) {
+
+
+
+       if (id_change || cap_raised) {
                /* We can't suid-execute if we're sharing parts of the executable */
                /* or if we're being traced (or if suid execs are not allowed)    */
                /* (current->mm->count > 1 is ok, as we'll get a new mm anyway)   */
@@ -653,8 +658,10 @@ int prepare_binprm(struct linux_binprm *bprm)
                    || (current->fs->count > 1)
                    || (atomic_read(&current->sig->count) > 1)
                    || (current->files->count > 1)) {
-                       if (!suser())
-                               return -EPERM;
+                       if (id_change && !capable(CAP_SETUID))
+                               return -EPERM;
+                       if (cap_raised && !capable(CAP_SETPCAP))
+                               return -EPERM;
                }
        }
 
@@ -669,7 +676,7 @@ int prepare_binprm(struct linux_binprm *bprm)
  * The formula used for evolving capabilities is:
  *
  *       pI' = pI
- *       pP' = fP | (fI & pI)
+ * (***) pP' = fP | (fI & pI)
  *       pE' = pP' & fE          [NB. fE is 0 or ~0]
  *
  * I=Inheritable, P=Permitted, E=Effective // p=process, f=file
@@ -678,11 +685,18 @@ int prepare_binprm(struct linux_binprm *bprm)
 
 void compute_creds(struct linux_binprm *bprm) 
 {
-       int new_permitted = bprm->cap_permitted.cap |
-               (bprm->cap_inheritable.cap & current->cap_inheritable.cap);
-
-       current->cap_permitted.cap = new_permitted;
-       current->cap_effective.cap = new_permitted & bprm->cap_effective.cap;
+       /* For init, we want to retain the capabilities set
+         * in the init_task struct. Thus we skip the usual
+         * capability rules */
+       if (current->pid != 1) {
+               int new_permitted = bprm->cap_permitted.cap |
+                       (bprm->cap_inheritable.cap & 
+                       current->cap_inheritable.cap);
+
+               current->cap_permitted.cap = new_permitted;
+               current->cap_effective.cap = new_permitted & 
+                                               bprm->cap_effective.cap;
+       }
        
         /* AUD: Audit candidate if current->cap_effective is set */
 
index 7555b9a6f5b6e3eadd15bc8ac64c952eea107bd5..111a2d6e05783b99150908d9383d0f1021eee378 100644 (file)
@@ -51,8 +51,11 @@ int ext2_permission (struct inode * inode, int mask)
         * Access is always granted for root. We now check last,
          * though, for BSD process accounting correctness
         */
-       if (((mode & mask & S_IRWXO) == mask) || fsuser())
+       if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
                return 0;
-       else
-               return -EACCES;
+       if ((mask == S_IROTH) ||
+           (S_ISDIR(mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
+               if (capable(CAP_DAC_READ_SEARCH))
+                       return 0;
+       return -EACCES;
 }
index de5b422eddecbc872b0b31d6d1b8f3f8113ac1cb..f4ee2921107a2475ca2beca39c2b888916618ebe 100644 (file)
@@ -383,7 +383,8 @@ int ext2_new_block (const struct inode * inode, unsigned long goal,
        if (le32_to_cpu(es->s_free_blocks_count) <= le32_to_cpu(es->s_r_blocks_count) &&
            ((sb->u.ext2_sb.s_resuid != current->fsuid) &&
             (sb->u.ext2_sb.s_resgid == 0 ||
-             !in_group_p (sb->u.ext2_sb.s_resgid)) && !fsuser())) {
+             !in_group_p (sb->u.ext2_sb.s_resgid)) && 
+            !capable(CAP_SYS_RESOURCE))) {
                unlock_super (sb);
                return 0;
        }
index 71c51809f4577448e9340f69c636bbb85f253854..d5e74cf35e3082f90d5b4ce1428657ad66cc09c5 100644 (file)
@@ -144,7 +144,7 @@ static inline void remove_suid(struct inode *inode)
 
        /* was any of the uid bits set? */
        mode &= inode->i_mode;
-       if (mode && !suser()) {
+       if (mode && !capable(CAP_FSETID)) {
                inode->i_mode &= ~mode;
                mark_inode_dirty(inode);
        }
index a48723031b6eec365e99fe27828812c19ec8f059..f0f2ca98f184df3341167c06a0cae19c41fb4a8e 100644 (file)
@@ -726,9 +726,9 @@ int ext2_notify_change(struct dentry *dentry, struct iattr *iattr)
             (ATTR_FLAG_APPEND | ATTR_FLAG_IMMUTABLE)) ^
            (inode->u.ext2_i.i_flags &
             (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
-               if (!fsuser())
+               if (!capable(CAP_LINUX_IMMUTABLE))
                        goto out;
-       } else if ((current->fsuid != inode->i_uid) && !fsuser())
+       } else if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                goto out;
 
        retval = inode_change_ok(inode, iattr);
index 70d4fc5634732b1bcf4e999c0f452cc29dce1a8a..3b58bc82253640927772f88ef8375c6db7729561 100644 (file)
@@ -39,10 +39,11 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
                    (inode->u.ext2_i.i_flags &
                     (EXT2_APPEND_FL | EXT2_IMMUTABLE_FL))) {
                        /* This test looks nicer. Thanks to Pauline Middelink */
-                       if (!fsuser())
+                       if (!capable(CAP_LINUX_IMMUTABLE))
                                return -EPERM;
                } else
-                       if ((current->fsuid != inode->i_uid) && !fsuser())
+                       if ((current->fsuid != inode->i_uid) && 
+                           !capable(CAP_FOWNER))
                                return -EPERM;
                if (IS_RDONLY(inode))
                        return -EROFS;
@@ -70,7 +71,7 @@ int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
        case EXT2_IOC_GETVERSION:
                return put_user(inode->u.ext2_i.i_version, (int *) arg);
        case EXT2_IOC_SETVERSION:
-               if ((current->fsuid != inode->i_uid) && !fsuser())
+               if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
                        return -EPERM;
                if (IS_RDONLY(inode))
                        return -EROFS;
index cc1fd35a5db1362a18eb6e451f415839773f8f23..40a2d30ae5ea1a1bb672d0302c3556f3e83ef7f0 100644 (file)
@@ -631,7 +631,7 @@ int ext2_rmdir (struct inode * dir, struct dentry *dentry)
        retval = -EPERM;
        if ((dir->i_mode & S_ISVTX) && 
            current->fsuid != inode->i_uid &&
-           current->fsuid != dir->i_uid && !fsuser())
+           current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_rmdir;
        if (inode == dir)       /* we may not delete ".", but "../dir" is ok */
                goto end_rmdir;
@@ -725,7 +725,7 @@ int ext2_unlink(struct inode * dir, struct dentry *dentry)
                goto end_unlink;
        if ((dir->i_mode & S_ISVTX) &&
            current->fsuid != inode->i_uid &&
-           current->fsuid != dir->i_uid && !fsuser())
+           current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_unlink;
 
        retval = -EIO;
@@ -923,7 +923,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
        retval = -EPERM;
        if ((old_dir->i_mode & S_ISVTX) && 
            current->fsuid != old_inode->i_uid &&
-           current->fsuid != old_dir->i_uid && !fsuser())
+           current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
                goto end_rename;
        if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode))
                goto end_rename;
@@ -964,7 +964,7 @@ static int do_ext2_rename (struct inode * old_dir, struct dentry *old_dentry,
        if (new_inode) {
                if ((new_dir->i_mode & S_ISVTX) &&
                    current->fsuid != new_inode->i_uid &&
-                   current->fsuid != new_dir->i_uid && !fsuser())
+                   current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
                        goto end_rename;
                if (IS_APPEND(new_inode) || IS_IMMUTABLE(new_inode))
                        goto end_rename;
index e6bf93e4b54eddc792975fccb394043f95cf552a..3155e72e4b01edaabdcb659cdaafd6f8e04c28a6 100644 (file)
@@ -416,7 +416,7 @@ int minix_rmdir(struct inode * dir, struct dentry *dentry)
 
         if ((dir->i_mode & S_ISVTX) &&
             current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !fsuser())
+            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_rmdir;
        if (inode->i_dev != dir->i_dev)
                goto end_rmdir;
@@ -482,7 +482,7 @@ repeat:
        }
        if ((dir->i_mode & S_ISVTX) &&
            current->fsuid != inode->i_uid &&
-           current->fsuid != dir->i_uid && !fsuser())
+           current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_unlink;
        if (de->inode != inode->i_ino) {
                retval = -ENOENT;
@@ -641,7 +641,7 @@ start_up:
        retval = -EPERM;
        if ((old_dir->i_mode & S_ISVTX) && 
            current->fsuid != old_inode->i_uid &&
-           current->fsuid != old_dir->i_uid && !fsuser())
+           current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
                goto end_rename;
        new_inode = new_dentry->d_inode;
        new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
@@ -673,7 +673,7 @@ start_up:
        retval = -EPERM;
        if (new_inode && (new_dir->i_mode & S_ISVTX) && 
            current->fsuid != new_inode->i_uid &&
-           current->fsuid != new_dir->i_uid && !fsuser())
+           current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
                goto end_rename;
        if (S_ISDIR(old_inode->i_mode)) {
                retval = -ENOTDIR;
index 06257ab99c63b7f2be27e6c37b1bb970cd4c1872..04ebe1fd98b121be49d814ca298ee04e11c035d2 100644 (file)
@@ -198,8 +198,13 @@ int permission(struct inode * inode,int mask)
                mode >>= 6;
        else if (in_group_p(inode->i_gid))
                mode >>= 3;
-       if (((mode & mask & 0007) == mask) || fsuser())
+       if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
                return 0;
+       /* read and search access */
+       if ((mask == S_IROTH) ||
+           (S_ISDIR(mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
+               if (capable(CAP_DAC_READ_SEARCH))
+                       return 0;
        return -EACCES;
 }
 
@@ -706,7 +711,7 @@ asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev)
 
        lock_kernel();
        error = -EPERM;
-       if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !fsuser()))
+       if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !capable(CAP_SYS_ADMIN)))
                goto out;
        error = -EINVAL;
        switch (mode & S_IFMT) {
index 7acaafade1ee65f44a9a69e40392362c8d143853..66c4ecd1fafaccdb946d9a1a63b2acef2ab9cdc5 100644 (file)
@@ -148,7 +148,7 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
        if (!initialized)
                nfsd_init();
        err = -EPERM;
-       if (!suser()) {
+       if (!capable(CAP_SYS_ADMIN)) {
                goto done;
        }
        err = -EFAULT;
index 204294cc3380dae450ec80bf45bccaba6718a8aa..6d23874f9aeebe2122138d44a7d4efdc3215a210 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -285,12 +285,14 @@ out:
 
 /*
  * access() needs to use the real uid/gid, not the effective uid/gid.
- * We do this by temporarily setting fsuid/fsgid to the wanted values
+ * We do this by temporarily clearing all FS-related capabilities and
+ * switching the fsuid/fsgid around to the real ones.
  */
 asmlinkage int sys_access(const char * filename, int mode)
 {
        struct dentry * dentry;
        int old_fsuid, old_fsgid;
+       kernel_cap_t old_cap;
        int res = -EINVAL;
 
        lock_kernel();
@@ -298,9 +300,15 @@ asmlinkage int sys_access(const char * filename, int mode)
                goto out;
        old_fsuid = current->fsuid;
        old_fsgid = current->fsgid;
+       old_cap = current->cap_effective;
+
        current->fsuid = current->uid;
        current->fsgid = current->gid;
 
+       /* Clear the capabilities if we switch to a non-root user */
+       if (current->uid)
+               cap_clear(current->cap_effective);
+
        dentry = namei(filename);
        res = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
@@ -310,6 +318,7 @@ asmlinkage int sys_access(const char * filename, int mode)
 
        current->fsuid = old_fsuid;
        current->fsgid = old_fsgid;
+       current->cap_effective = old_cap;
 out:
        unlock_kernel();
        return res;
@@ -411,7 +420,7 @@ asmlinkage int sys_chroot(const char * filename)
                goto dput_and_out;
 
        error = -EPERM;
-       if (!fsuser())
+       if (!capable(CAP_SYS_CHROOT))
                goto dput_and_out;
 
        /* exchange dentries */
@@ -833,7 +842,7 @@ asmlinkage int sys_vhangup(void)
        int ret = -EPERM;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_TTY_CONFIG))
                goto out;
        /* If there is a controlling tty, hang it up */
        if (current->tty)
index 79ac2c38bc34f874989a783d89b94f1eb533ca58..125be772a088ab4c242fa9c8ce743f7e0c89e8b7 100644 (file)
@@ -764,6 +764,17 @@ static inline char * task_sig(struct task_struct *p, char *buffer)
        return buffer;
 }
 
+extern inline char *task_cap(struct task_struct *p, char *buffer)
+{
+    return buffer + sprintf(buffer, "CapInh:\t%016x\n"
+                           "CapPrm:\t%016x\n"
+                           "CapEff:\t%016x\n",
+                           p->cap_inheritable.cap,
+                           p->cap_permitted.cap,
+                           p->cap_effective.cap);
+}
+
+
 static int get_status(int pid, char * buffer)
 {
        char * orig = buffer;
@@ -778,6 +789,7 @@ static int get_status(int pid, char * buffer)
        buffer = task_state(tsk, buffer);
        buffer = task_mem(tsk, buffer);
        buffer = task_sig(tsk, buffer);
+       buffer = task_cap(tsk, buffer);
        return buffer - orig;
 }
 
index b2feaeef120c24404a646262b84b4abab25dc67a..b4ca1094c4a7f1dd9822ed1f5e6e03207a4c11d6 100644 (file)
@@ -145,8 +145,13 @@ static int standard_permission(struct inode *inode, int mask)
                mode >>= 6;
        else if (in_group_p(inode->i_gid))
                mode >>= 3;
-       if (((mode & mask & 0007) == mask) || fsuser())
+       if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))
                return 0;
+       /* read and search access */
+       if ((mask == S_IROTH) ||
+           (S_ISDIR(mode)  && !(mask & ~(S_IROTH | S_IXOTH))))
+               if (capable(CAP_DAC_READ_SEARCH))
+                       return 0;
        return -EACCES;
 }
 
index 34f9f969f24c4fc6efa51865b7de678cc5546424..5597c2e6d93139b5739a5976fd6fdcb3b42a9e65 100644 (file)
@@ -630,7 +630,8 @@ printk("smb_newconn: fd=%d, pid=%d\n", opt->fd, current->pid);
                goto out;
 
        error = -EACCES;
-       if (current->uid != server->mnt->mounted_uid && !suser())
+       if (current->uid != server->mnt->mounted_uid && 
+           !capable(CAP_SYS_ADMIN))
                goto out;
 
        error = -EBADF;
index 0433dd251d2d1692cba8e18340a63b644d2cf9f9..b28b5f0b605b8cedaaf5454e0e2a5dade8c3fc9b 100644 (file)
@@ -743,7 +743,7 @@ asmlinkage int sys_umount(char * name)
        struct dentry * dentry;
        int retval;
 
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        lock_kernel();
@@ -985,7 +985,7 @@ asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
        struct file dummy;      /* allows read-write or read-only flag */
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                goto out;
        if ((new_flags &
             (MS_MGC_MSK | MS_REMOUNT)) == (MS_MGC_VAL | MS_REMOUNT)) {
index 270cfe63752465db10ef1b4b8e038c0781c677a5..60b50720aae7067fc27ac4bb5fa651e1411e6151 100644 (file)
@@ -419,7 +419,7 @@ int sysv_rmdir(struct inode * dir, struct dentry * dentry)
 
         if ((dir->i_mode & S_ISVTX) &&
             current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !fsuser())
+            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_rmdir;
        if (inode->i_dev != dir->i_dev)
                goto end_rmdir;
@@ -484,7 +484,7 @@ repeat:
        }
        if ((dir->i_mode & S_ISVTX) &&
            current->fsuid != inode->i_uid &&
-           current->fsuid != dir->i_uid && !fsuser())
+           current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
                goto end_unlink;
        if (de->inode != inode->i_ino) {
                retval = -ENOENT;
@@ -643,7 +643,7 @@ start_up:
        retval = -EPERM;
        if ((old_dir->i_mode & S_ISVTX) && 
            current->fsuid != old_inode->i_uid &&
-           current->fsuid != old_dir->i_uid && !fsuser())
+           current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
                goto end_rename;
        new_inode = new_dentry->d_inode;
        new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name,
@@ -675,7 +675,7 @@ start_up:
        retval = -EPERM;
        if (new_inode && (new_dir->i_mode & S_ISVTX) && 
            current->fsuid != new_inode->i_uid &&
-           current->fsuid != new_dir->i_uid && !fsuser())
+           current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
                goto end_rename;
        if (S_ISDIR(old_inode->i_mode)) {
                retval = -ENOTDIR;
index be72a9cb48ae90612865456ebc4345718fcd5833..7b549fd963fb9a66e3e8fecf2fad049e963c0b76 100644 (file)
@@ -350,14 +350,14 @@ static int umsdos_rename_f(
     Printk (("ret %d ",ret));
     if (ret == 0){
       /* check sticky bit on old_dir */
-      if ( !(old_dir->i_mode & S_ISVTX) || fsuser() ||
+      if ( !(old_dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
           current->fsuid == old_info.entry.uid ||
           current->fsuid == old_dir->i_uid ) {
        /* Does new_name already exist? */
        PRINTK(("new findentry "));
        ret = umsdos_findentry(new_dir,&new_info,0);
        if (ret != 0 || /* if destination file exists, are we allowed to replace it ? */
-           !(new_dir->i_mode & S_ISVTX) || fsuser() ||
+           !(new_dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
            current->fsuid == new_info.entry.uid ||
            current->fsuid == new_dir->i_uid ) {
          PRINTK (("new newentry "));
@@ -933,7 +933,7 @@ int UMSDOS_rmdir(
         umsdos_real_lookup (dir, tdentry);     /* fill inode part */
        Printk (("isempty %d i_count %d ",empty,sdir->i_count));
                                /* check sticky bit */
-       if ( !(dir->i_mode & S_ISVTX) || fsuser() ||
+       if ( !(dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
             current->fsuid == sdir->i_uid ||
             current->fsuid == dir->i_uid ) {
          if (empty == 1){
@@ -1024,7 +1024,7 @@ int UMSDOS_unlink (
       if (ret == 0){
        Printk (("UMSDOS_unlink %.*s ",info.fake.len,info.fake.fname));
                                /* check sticky bit */
-       if ( !(dir->i_mode & S_ISVTX) || fsuser() ||
+       if ( !(dir->i_mode & S_ISVTX) || capable(CAP_FOWNER) ||
             current->fsuid == info.entry.uid ||
             current->fsuid == dir->i_uid ) {
          if (info.entry.flags & UMSDOS_HLINK){
index bef18652908ad22d235d42014bd2abee3e3f0868..e8de11f1273115f844a1290dee0ac62d9bd9ee2c 100644 (file)
@@ -19,7 +19,7 @@ typedef unsigned short ide_ioreg_t;
 #define MAX_HWIFS      4
 #endif
 
-#define ide_sti()      sti()
+#define ide__sti()     __sti()
 
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
index 8ad19c2f4df08273047fc8a84252254b28fa77b7..0d4ab6b214c725c11a33deef9050bbf44e124d8a 100644 (file)
@@ -116,5 +116,17 @@ extern inline void init_new_context(struct mm_struct *mm)
 
 #define destroy_context(mm)    do { } while(0)
 
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ * Ideally this would be an extern inline function, but reload_context
+ * is declared in pgtable.h, which includes this file. :-(
+ */
+#define activate_context(tsk)          \
+       do {                            \
+               get_mmu_context(tsk);   \
+               reload_context(tsk);    \
+       } while (0)
+
 #endif
 
index 3710c291121075d5a2dfc73295278e88eece7240..2ead7b36a13a87b22e20f51e6066dc325fc13983 100644 (file)
@@ -19,7 +19,7 @@ typedef unsigned long ide_ioreg_t;
 #define MAX_HWIFS      4
 #endif
 
-#define ide_sti()      sti()
+#define ide__sti()     __sti()
 
 #include <asm/arch/ide.h>
 
index 7325fbaa49f7eb14eefb53227faa0d0494a916ee..f6e4c3e330e0dfb5e0908b6b18484e11d7e83f54 100644 (file)
@@ -13,5 +13,6 @@
 
 #define init_new_context(mm)   do { } while(0)
 #define destroy_context(mm)    do { } while(0)
+#define activate_context(tsk)  do { } while(0)
 
 #endif
index e61802fec61ee375272383e070cd4b44e1230294..a6d1fc868e9f32af934e4714cba845cc2bab96ae 100644 (file)
@@ -19,7 +19,7 @@ typedef unsigned short ide_ioreg_t;
 #define MAX_HWIFS      6
 #endif
 
-#define ide_sti()      sti()
+#define ide__sti()     __sti()
 
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
index 01b8bfcbacbddc60f6c4b831be86dad67e62aa5b..e8b812e2f83da77209c1826e9f84ba148c97e86c 100644 (file)
@@ -8,5 +8,6 @@
 
 #define init_new_context(mm)   do { } while(0)
 #define destroy_context(mm)    do { } while(0)
+#define activate_context(tsk)  do { } while(0)
 
 #endif
index 48c586d6c7707e44ca54f33768780f227ea09ffa..e6a42b2279441e3c9e84a1343ee6a2d20a6dd910 100644 (file)
@@ -3,6 +3,10 @@
 
 #ifndef __SMP__
 
+#define DEBUG_SPINLOCKS        0       /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
+
+#if (DEBUG_SPINLOCKS < 1)
+
 /*
  * Your basic spinlocks, allowing only a single CPU anywhere
  */
@@ -11,7 +15,7 @@ typedef struct { } spinlock_t;
 
 #define spin_lock_init(lock)   do { } while(0)
 #define spin_lock(lock)                do { } while(0)
-#define spin_trylock(lock)     do { } while(0)
+#define spin_trylock(lock)     (1)
 #define spin_unlock_wait(lock) do { } while(0)
 #define spin_unlock(lock)      do { } while(0)
 #define spin_lock_irq(lock)    cli()
@@ -22,6 +26,52 @@ typedef struct { } spinlock_t;
 #define spin_unlock_irqrestore(lock, flags) \
        restore_flags(flags)
 
+#elif (DEBUG_SPINLOCKS < 2)
+
+typedef struct {
+       volatile unsigned int lock;
+} spinlock_t;
+#define SPIN_LOCK_UNLOCKED { 0 }
+
+#define spin_lock_init(x)      do { (x)->lock = 0; } while (0)
+#define spin_trylock(lock)     (!test_and_set_bit(0,(lock)))
+
+#define spin_lock(x)           do { (x)->lock = 1; } while (0)
+#define spin_unlock_wait(x)    do { } while (0)
+#define spin_unlock(x)         do { (x)->lock = 0; } while (0)
+#define spin_lock_irq(x)       do { cli(); spin_lock(x); } while (0)
+#define spin_unlock_irq(x)     do { spin_unlock(x); sti(); } while (0)
+
+#define spin_lock_irqsave(x, flags) \
+       do { save_flags(flags); spin_lock_irq(x); } while (0)
+#define spin_unlock_irqrestore(x, flags) \
+       do { spin_unlock(x); restore_flags(flags); } while (0)
+
+#else /* (DEBUG_SPINLOCKS >= 2) */
+
+typedef struct {
+       volatile unsigned int lock;
+       volatile unsigned int babble;
+       const char *module;
+} spinlock_t;
+#define SPIN_LOCK_UNLOCKED { 0, 25, __BASE_FILE__ }
+
+#include <linux/kernel.h>
+
+#define spin_lock_init(x)      do { (x)->lock = 0; } while (0)
+#define spin_trylock(lock)     (!test_and_set_bit(0,(lock)))
+
+#define spin_lock(x)           do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
+#define spin_unlock_wait(x)    do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
+#define spin_unlock(x)         do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
+#define spin_lock_irq(x)       do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
+#define spin_unlock_irq(x)     do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; sti();} while (0)
+
+#define spin_lock_irqsave(x,flags)      do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
+#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
+
+#endif /* DEBUG_SPINLOCKS */
+
 /*
  * Read-write spinlocks, allowing multiple readers
  * but only one writer.
@@ -53,13 +103,10 @@ typedef struct { } rwlock_t;
 #define write_unlock_irqrestore(lock, flags) \
        restore_flags(flags)
 
-#else
+#else  /* __SMP__ */
 
 /*
- * Simple spin lock operations.  There are two variants, one clears IRQ's
- * on the local processor, one does not.
- *
- * We make no fairness assumptions. They have a cost.
+ * Your basic spinlocks, allowing only a single CPU anywhere
  */
 
 typedef struct {
@@ -69,6 +116,13 @@ typedef struct {
 #define SPIN_LOCK_UNLOCKED { 0 }
 
 #define spin_lock_init(x)      do { (x)->lock = 0; } while(0)
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
 #define spin_unlock_wait(x)    do { barrier(); } while(((volatile spinlock_t *)(x))->lock)
 
 typedef struct { unsigned long a[100]; } __dummy_lock_t;
@@ -176,5 +230,5 @@ typedef struct {
 #define write_unlock_irqrestore(lock, flags) \
        do { write_unlock(lock); __restore_flags(flags); } while (0)
 
-#endif /* SMP */
+#endif /* __SMP__ */
 #endif /* __ASM_SPINLOCK_H */
index 3ac10a193a86c05c675abc32596710e8ac5bdeda..018f6f0f54073e6afdea00002144a338961be16e 100644 (file)
 #define __NR_pwrite            181
 #define __NR_chown             182
 #define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
 
 /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
 
index 0a0222ac5b1c698a0a802e1585665a6660a1b370..a69ef5b180ecd820df063ad435097e6e66c5ad21 100644 (file)
@@ -424,17 +424,17 @@ static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *,
  * works. (Roman)
  */
 #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA)
-#define        ide_sti()                                       \
+#define        ide__sti()                                      \
     do {                                               \
-       if (!in_interrupt()) sti();                     \
+       if (!in_interrupt()) __sti();                   \
     } while(0)
 #elif defined(CONFIG_ATARI)
-#define        ide_sti()                                               \
+#define        ide__sti()                                              \
     do {                                                       \
        if (!MACH_IS_ATARI || !in_interrupt()) sti();           \
     } while(0)
 #else /* !defined(CONFIG_ATARI) */
-#define        ide_sti()       sti()
+#define        ide__sti()      __sti()
 #endif
 
 #endif /* __KERNEL__ */
index 853ce4b71027f9e91e452ac0a4d8f078a9133da3..4850dd40415ea03eb29ddfe67c8c3c52f09f5a89 100644 (file)
@@ -8,5 +8,6 @@
 
 #define init_new_context(mm)   do { } while(0)
 #define destroy_context(mm)    do { } while(0)
+#define activate_context(tsk)  do { } while(0)
 
 #endif
index bda27206dea5866fe599c85d9213e0a4444d5526..733661667910ed59b77a59d1358f93e6309a9c1e 100644 (file)
@@ -19,7 +19,7 @@ typedef unsigned short ide_ioreg_t;
 #define MAX_HWIFS      4
 #endif
 
-#define ide_sti()      sti()
+#define ide__sti()     __sti()
 
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
index 87b12792e44ce32bc00f983fe4c7ba90571e0c0c..5010f4d349ce8e033b4d1f7a10c66c8de7fdc5f6 100644 (file)
@@ -62,4 +62,14 @@ extern inline void destroy_context(struct mm_struct *mm)
        mm->context = 0;
 }
 
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+extern inline activate_context(struct task_struct *tsk)
+{
+       get_mmu_context(tsk);
+       /* XXX here we presumably need to set some cpu register - paulus. */
+}
+
 #endif /* __ASM_MIPS_MMU_CONTEXT_H */
index efbd4b363cdd5eb93a22a0d6a00b8bca4a2a6174..d9e25bacebbbb4d49baaec2ecb6ec1198fcf653d 100644 (file)
@@ -26,7 +26,7 @@
 #define SUPPORT_VLB_SYNC       0
 
 
-#define ide_sti()      sti()
+#define ide__sti()     __sti()
 
 typedef unsigned int ide_ioreg_t;
 void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
index d715f4ca4d6756a5eb7dc9cf84b1a7df3a9eb7ce..0f06f16fe3350ef5a6f6c943950d4783f0a38cbb 100644 (file)
 #ifdef CONFIG_8xx
 #define NO_CONTEXT      16
 #define LAST_CONTEXT    15
+#define MUNGE_CONTEXT(n)        (n)
+
 #else
+
+/* PPC 6xx, 7xx CPUs */
 #define NO_CONTEXT      0
 #define LAST_CONTEXT    0xfffff
+
+/*
+ * Allocating context numbers this way tends to spread out
+ * the entries in the hash table better than a simple linear
+ * allocation.
+ */
+#define MUNGE_CONTEXT(n)        (((n) * 897) & LAST_CONTEXT)
 #endif
 
 extern int next_mmu_context;
@@ -36,17 +47,6 @@ extern void set_context(int context);
 #define set_context(context)    do { } while (0)
 #endif
 
-#ifndef CONFIG_8xx
-/*
- * Allocating context numbers this way tends to spread out
- * the entries in the hash table better than a simple linear
- * allocation.
- */
-#define MUNGE_CONTEXT(n)        (((n) * 897) & LAST_CONTEXT)
-#else
-#define MUNGE_CONTEXT(n)        (n)
-#endif
-
 /*
  * Get a new mmu context for task tsk if necessary.
  */
@@ -57,8 +57,6 @@ do {                                                          \
                if (next_mmu_context == LAST_CONTEXT)           \
                        mmu_context_overflow();                 \
                mm->context = MUNGE_CONTEXT(++next_mmu_context);\
-               if ( tsk == current )                           \
-                       set_context(mm->context);               \
        }                                                       \
 } while (0)
 
@@ -70,11 +68,17 @@ do {                                                                \
 /*
  * We're finished using the context for an address space.
  */
-#ifdef CONFIG_8xx
 #define destroy_context(mm)     ((mm)->context = NO_CONTEXT)
-#else
-#define destroy_context(mm)     do { } while (0)
-#endif
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+extern inline void activate_context(struct task_struct *tsk)
+{
+       get_mmu_context(tsk);
+       set_context(tsk->mm->context);
+}
 
 /*
  * compute the vsid from the context and segment
index d6ac7e9229dfb78749983dbe19e274c84fad6ba0..d73b71f94727c1ab371a04fb7e366c7fa7e3119a 100644 (file)
@@ -22,4 +22,11 @@ BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
 
 #define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
 
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ * XXX this presumably needs a sensible implementation - paulus.
+ */
+#define activate_context(tsk)  do { } while(0)
+
 #endif /* !(__SPARC_MMU_CONTEXT_H) */
index f72c264c8b0cf4e393bec497b6ed89315b9940e0..acd59330303e10a9824c660b72f4a24229e5c936 100644 (file)
@@ -15,7 +15,7 @@ typedef unsigned long ide_ioreg_t;
 #undef  MAX_HWIFS
 #define MAX_HWIFS      2
 
-#define        ide_sti()       sti()
+#define        ide__sti()      __sti()
 
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
@@ -38,7 +38,7 @@ static __inline__ void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int
        for ( ; i < 10; i++)
                *p++ = 0;
        /* PCI code needs to figure out this. */
-       if(irq != NULL)
+       if (irq != NULL)
                *irq = 0;
 }
 
index b92481dd54f71414a549f94775c522138752cb3e..44209a12057512a483d3c8f53cdb590300b43ed5 100644 (file)
@@ -72,6 +72,12 @@ extern __inline__ void get_mmu_context(struct task_struct *tsk)
          : "o4");
 }
 
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+#define activate_context(tsk)  get_mmu_context(tsk)
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__SPARC64_MMU_CONTEXT_H) */
index 5101379f49ef045672f366a47a1c758b05345ebf..d7dc45db6104df2d9c706c2ef46d8f113c828850 100644 (file)
@@ -95,7 +95,7 @@ void initrd_init(void);
 #endif
 
 #define RO_IOCTLS(dev,where) \
-  case BLKROSET: { int __val;  if (!suser()) return -EACCES; \
+  case BLKROSET: { int __val;  if (!capable(CAP_SYS_ADMIN)) return -EACCES; \
                   if (get_user(__val, (int *)(where))) return -EFAULT; \
                   set_device_ro((dev),__val); return 0; } \
   case BLKROGET: { int __val = (is_read_only(dev) != 0) ; \
@@ -411,14 +411,20 @@ void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
 
 #ifdef IDE_DRIVER
 void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) {
-       struct request *req = hwgroup->rq;
+       int nsect;
+       struct buffer_head *bh;
+       struct request *req;
+       unsigned long flags;
+
+       spin_lock_irqsave(&io_request_lock,flags);
+       req = hwgroup->rq;
 #else
 static void end_request(int uptodate) {
-       struct request *req = CURRENT;
-#endif /* IDE_DRIVER */
-       struct buffer_head * bh;
        int nsect;
+       struct buffer_head *bh;
+       struct request *req = CURRENT;
 
+#endif /* IDE_DRIVER */
        req->errors = 0;
        if (!uptodate) {
                printk("end_request: I/O error, dev %s, sector %lu\n",
@@ -443,6 +449,9 @@ static void end_request(int uptodate) {
                                printk("end_request: buffer-list destroyed\n");
                        }
                        req->buffer = bh->b_data;
+#ifdef IDE_DRIVER
+                       spin_unlock_irqrestore(&io_request_lock,flags);
+#endif /* IDE_DRIVER */
                        return;
                }
        }
@@ -461,6 +470,9 @@ static void end_request(int uptodate) {
                up(req->sem);
        req->rq_status = RQ_INACTIVE;
        wake_up(&wait_for_request);
+#ifdef IDE_DRIVER
+       spin_unlock_irqrestore(&io_request_lock,flags);
+#endif /* IDE_DRIVER */
 }
 #endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */
 #endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
index db737e55f042d0dc9ecc4a3ec28290db7aae45b8..a0342601f2f84e42cf53d32c036cf330dbc5e531 100644 (file)
    kernel might be somewhat backwards compatible, but don't bet on
    it. */
 
+/* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to
+   a set of three capability sets.  The transposition of 3*the
+   following structure to such a composite is better handled in a user
+   library since the draft standard requires the use of malloc/free
+   etc.. */
 #define _LINUX_CAPABILITY_VERSION  0x19980330
 
-typedef struct _user_cap_struct {
+typedef struct __user_cap_header_struct {
        __u32 version;
-       __u32 size;
-       __u8  cap[1];
-} *cap_t;
-
+       int pid;
+} *cap_user_header_t;
+typedef struct __user_cap_data_struct {
+        __u32 effective;
+        __u32 permitted;
+        __u32 inheritable;
+} *cap_user_data_t;
+  
 #ifdef __KERNEL__
 
 typedef struct kernel_cap_struct {
-       int cap;
+       __u32 cap;
 } kernel_cap_t;
+  
+#define _USER_CAP_HEADER_SIZE  (2*sizeof(__u32))
+#define _KERNEL_CAP_T_SIZE     (sizeof(kernel_cap_t))
 
 #endif
 
@@ -46,13 +60,13 @@ typedef struct kernel_cap_struct {
 
 /* Override all DAC access, including ACL execute access if
    [_POSIX_ACL] is defined. Excluding DAC access covered by
-   CAP_LINUX_IMMUTABLE */
+   CAP_LINUX_IMMUTABLE. */
 
 #define CAP_DAC_OVERRIDE     1
 
 /* Overrides all DAC restrictions regarding read and search on files
    and directories, including ACL restrictions if [_POSIX_ACL] is
-   defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE */
+   defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */
 
 #define CAP_DAC_READ_SEARCH  2
     
@@ -82,10 +96,13 @@ typedef struct kernel_cap_struct {
 #define CAP_KILL             5
 
 /* Allows setgid(2) manipulation */
+/* Allows setgroups(2) */
+/* Allows forged gids on socket credentials passing. */
 
 #define CAP_SETGID           6
 
-/* Allows setuid(2) manipulation */
+/* Allows set*uid(2) manipulation (including fsuid). */
+/* Allows forged pids on socket credentials passing. */
 
 #define CAP_SETUID           7
 
@@ -112,9 +129,17 @@ typedef struct kernel_cap_struct {
 #define CAP_NET_BROADCAST    11
 
 /* Allow interface configuration */
-/* Allow configuring of firewall stuff */
+/* Allow administration of IP firewall, masquerading and accounting */
 /* Allow setting debug option on sockets */
 /* Allow modification of routing tables */
+/* Allow setting arbitrary process / process group ownership on
+   sockets */
+/* Allow binding to any address for transparent proxying */
+/* Allow setting TOS (type of service) */
+/* Allow setting promiscuous mode */
+/* Allow clearing driver statistics */
+/* Allow multicasting */
+/* Allow read/write of device-specific registers */
 
 #define CAP_NET_ADMIN        12
 
@@ -123,7 +148,9 @@ typedef struct kernel_cap_struct {
 
 #define CAP_NET_RAW          13
 
-/* Allow locking of segments in memory */
+/* Allow locking of shared memory segments */
+/* Allow mlock and mlockall (which doesn't really have anything to do
+   with IPC) */
 
 #define CAP_IPC_LOCK         14
 
@@ -153,9 +180,42 @@ typedef struct kernel_cap_struct {
 
 /* Allow configuration of the secure attention key */
 /* Allow administration of the random device */
-/* Allow device administration */
+/* Allow device administration (mknod)*/
 /* Allow examination and configuration of disk quotas */
-/* System Admin functions: mount et al */
+/* Allow configuring the kernel's syslog (printk behaviour) */
+/* Allow sending a signal to any process */
+/* Allow setting the domainname */
+/* Allow setting the hostname */
+/* Allow calling bdflush() */
+/* Allow mount() and umount(), setting up new smb connection */
+/* Allow some autofs root ioctls */
+/* Allow nfsservctl */
+/* Allow VM86_REQUEST_IRQ */
+/* Allow to read/write pci config on alpha */
+/* Allow irix_prctl on mips (setstacksize) */
+/* Allow flushing all cache on m68k (sys_cacheflush) */
+/* Allow removing semaphores */
+/* Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores
+   and shared memory */
+/* Allow locking/unlocking of shared memory segment */
+/* Allow turning swap on/off */
+/* Allow forged pids on socket credentials passing */
+/* Allow setting readahead and flushing buffers on block devices */
+/* Allow setting geometry in floppy driver */
+/* Allow turning DMA on/off in xd driver */
+/* Allow administration of md devices (mostly the above, but some
+   extra ioctls) */
+/* Allow tuning the ide driver */
+/* Allow access to the nvram device */
+/* Allow administration of apm_bios, serial and bttv (TV) device */
+/* Allow manufacturer commands in isdn CAPI support driver */
+/* Allow reading non-standardized portions of pci configuration space */
+/* Allow DDI debug ioctl on sbpcd driver */
+/* Allow setting up serial ports */
+/* Allow sending raw qic-117 commands */
+/* Allow enabling/disabling tagged queuing on SCSI controllers and sending
+   arbitrary SCSI commands */
+/* Allow setting encryption key on loopback filesystem */
 
 #define CAP_SYS_ADMIN        21
 
@@ -163,19 +223,34 @@ typedef struct kernel_cap_struct {
 
 #define CAP_SYS_BOOT         22
 
-/* Allow use of renice() on others, and raising of priority */
+/* Allow raising priority and setting priority on other (different
+   UID) processes */
+/* Allow use of FIFO and round-robin (realtime) scheduling on own
+   processes and setting the scheduling algorithm used by another
+   process. */
 
 #define CAP_SYS_NICE         23
 
-/* Override resource limits */
+/* Override resource limits. Set resource limits. */
+/* Override quota limits. */
+/* Override reserved space on ext2 filesystem */
+/* NOTE: ext2 honors fsuid when checking for resource overrides, so 
+   you can override using fsuid too */
+/* Override size restrictions on IPC message queues */
+/* Allow more than 64hz interrupts from the real-time clock */
+/* Override max number of consoles on console allocation */
+/* Override max number of keymaps */
 
 #define CAP_SYS_RESOURCE     24
 
 /* Allow manipulation of system clock */
+/* Allow irix_stime on mips */
+/* Allow setting the real-time clock */
 
 #define CAP_SYS_TIME         25
 
 /* Allow configuration of tty devices */
+/* Allow vhangup() of tty */
 
 #define CAP_SYS_TTY_CONFIG   26
 
@@ -187,17 +262,48 @@ typedef struct kernel_cap_struct {
 
 #define CAP_EMPTY_SET       {  0 }
 #define CAP_FULL_SET        { ~0 }
+#define CAP_INIT_EFF_SET    { ~0 & ~CAP_TO_MASK(CAP_SETPCAP) }
+#define CAP_INIT_INH_SET    { ~0 & ~CAP_TO_MASK(CAP_SETPCAP) }
 
 #define CAP_TO_MASK(x) (1 << (x))
-#define cap_raise(c, flag)   (c.cap |=  CAP_TO_MASK(flag))
-#define cap_lower(c, flag)   (c.cap &= ~CAP_TO_MASK(flag))
-#define cap_raised(c, flag)  (c.cap &   CAP_TO_MASK(flag))
-
-#define cap_isclear(c) (!c.cap)
-
-#define cap_copy(dest,src) do { (dest).cap = (src).cap; } while(0)
-#define cap_clear(c)       do {  c.cap =  0; } while(0)
-#define cap_set_full(c)    do {  c.cap = ~0; } while(0)
+#define cap_raise(c, flag)   ((c).cap |=  CAP_TO_MASK(flag))
+#define cap_lower(c, flag)   ((c).cap &= ~CAP_TO_MASK(flag))
+#define cap_raised(c, flag)  ((c).cap &   CAP_TO_MASK(flag))
+
+static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
+{
+     kernel_cap_t dest;
+     dest.cap = a.cap | b.cap;
+     return dest;
+}
+
+static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
+{
+     kernel_cap_t dest;
+     dest.cap = a.cap & b.cap;
+     return dest;
+}
+
+static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
+{
+     kernel_cap_t dest;
+     dest.cap = a.cap & ~drop.cap;
+     return dest;
+}
+
+static inline kernel_cap_t cap_invert(kernel_cap_t c)
+{
+     kernel_cap_t dest;
+     dest.cap = ~c.cap;
+     return dest;
+}
+
+#define cap_isclear(c)       (!(c).cap)
+#define cap_issubset(a,set)  (!((a).cap & ~(set).cap))
+
+#define cap_clear(c)         do { (c).cap =  0; } while(0)
+#define cap_set_full(c)      do { (c).cap = ~0; } while(0)
+#define cap_mask(c,mask)     do { (c).cap &= (mask).cap; } while(0)
 
 #define cap_is_fs_cap(c)     ((c) & CAP_FS_MASK)
 
index 9be5bd1b1c61dca02e58c47988e1f3e600a9e246..bb343ac2e057dfd06b04edecd7c0007879c4f6f7 100644 (file)
@@ -45,7 +45,7 @@
 #define WIN_VERIFY             0x40
 #define WIN_FORMAT             0x50
 #define WIN_INIT               0x60
-#define WIN_SEEK               0x70
+#define WIN_SEEK               0x70
 #define WIN_DIAGNOSE           0x90
 #define WIN_SPECIFY            0x91    /* set drive geometry translation */
 #define WIN_SETIDLE1           0xE3
@@ -101,12 +101,13 @@ struct hd_geometry {
 #define HDIO_GETGEO            0x0301  /* get device geometry */
 #define HDIO_GET_UNMASKINTR    0x0302  /* get current unmask setting */
 #define HDIO_GET_MULTCOUNT     0x0304  /* get current IDE blockmode setting */
-#define HDIO_GET_IDENTITY      0x0307  /* get IDE identification info */
-#define HDIO_GET_KEEPSETTINGS  0x0308  /* get keep-settings-on-reset flag */
-#define HDIO_GET_32BIT                 0x0309  /* get current io_32bit setting */
+#define HDIO_OBSOLETE_IDENTITY 0x0307  /* OBSOLETE, DO NOT USE: returns 142 bytes */
+#define HDIO_GET_KEEPSETTINGS  0x0308  /* get keep-settings-on-reset flag */
+#define HDIO_GET_32BIT         0x0309  /* get current io_32bit setting */
 #define HDIO_GET_NOWERR                0x030a  /* get ignore-write-error flag */
 #define HDIO_GET_DMA           0x030b  /* get use-dma flag */
 #define HDIO_GET_NICE          0x030c  /* get nice flags */
+#define HDIO_GET_IDENTITY      0x030d  /* get IDE identification info */
 #define HDIO_DRIVE_CMD         0x031f  /* execute a special drive command */
 
 /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
index ba2e34f07c47598700ccff456952d7159bd2e194..b50c6b43459122c10170b66f323249293c3c37bf 100644 (file)
 #define LP_EXIST 0x0001
 #define LP_SELEC 0x0002
 #define LP_BUSY         0x0004
+#define LP_BUSY_BIT_POS 2
 #define LP_OFFL         0x0008
 #define LP_NOPA  0x0010
 #define LP_ERR   0x0020
 #define LP_ABORT 0x0040
+#ifdef LP_NEED_CAREFUL
 #define LP_CAREFUL 0x0080
+#endif
 #define LP_ABORTOPEN 0x0100
 
 /* timeout for each character.  This is relative to bus cycles -- it
                            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
 #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) */
 #define LPRESET     0x060c  /* reset printer */
+#ifdef LP_STATS
 #define LPGETSTATS  0x060d  /* get statistics (struct lp_stats) */
+#endif
 #define LPGETFLAGS  0x060e  /* get status flags */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
 #define LP_WAIT(minor) lp_table[(minor)].wait          /* strobe wait */
 #define LP_IRQ(minor)  lp_table[(minor)].dev->port->irq /* interrupt # */
                                                        /* 0 means polled */
+#ifdef LP_STATS
 #define LP_STAT(minor) lp_table[(minor)].stats         /* statistics area */
+#endif
 #define LP_BUFFER_SIZE 256
 
 #define LP_BASE(x)     lp_table[(x)].dev->port->base
 
+#ifdef LP_STATS
 struct lp_stats {
        unsigned long chars;
        unsigned long sleeps;
@@ -103,6 +113,7 @@ struct lp_stats {
        unsigned int meanwait;
        unsigned int mdev;
 };
+#endif
 
 struct lp_struct {
        struct pardevice *dev;
@@ -111,10 +122,13 @@ struct lp_struct {
        unsigned int time;
        unsigned int wait;
        char *lp_buffer;
+#ifdef LP_STATS
        unsigned int lastcall;
        unsigned int runchars;
-       unsigned int waittime;
        struct lp_stats stats;
+#endif
+       struct wait_queue *wait_q;
+       unsigned int last_error;
 };
 
 /*
@@ -160,7 +174,7 @@ struct lp_struct {
  */
 #define LP_DELAY       50
 
-#define LP_POLLING(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
+#define LP_POLLED(minor) (lp_table[(minor)].dev->port->irq == PARPORT_IRQ_NONE)
 #define LP_PREEMPTED(minor) (lp_table[(minor)].dev->port->waithead != NULL)
 
 /*
index 96e85496a91a62a9819a5ac4eb9fe17049a0813a..1cd2905dea698cd463543a87b892396a3b5d6eb1 100644 (file)
@@ -379,7 +379,6 @@ extern struct inode_operations proc_dir_inode_operations;
 extern struct inode_operations proc_file_inode_operations;
 extern struct inode_operations proc_net_inode_operations;
 extern struct inode_operations proc_netdir_inode_operations;
-extern struct inode_operations proc_scsi_inode_operations;
 extern struct inode_operations proc_openprom_inode_operations;
 extern struct inode_operations proc_mem_inode_operations;
 extern struct inode_operations proc_sys_inode_operations;
@@ -396,8 +395,6 @@ extern struct inode_operations proc_ringbuf_inode_operations;
 extern struct inode_operations proc_omirr_inode_operations;
 extern struct inode_operations proc_ppc_htab_inode_operations;
 
-#endif
-
 /*
  * generic.c
  */
@@ -416,3 +413,5 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver);
  * proc_devtree.c
  */
 extern void proc_device_tree_init(void);
+
+#endif /* _LINUX_PROC_FS_H */
index ceeea5d427cbd1ba60a4fd436ce1ba926f6525a4..a1b2f3559f1722156d4b7eda5a1dc9490bccaea3 100644 (file)
@@ -354,7 +354,7 @@ struct task_struct {
 /* process credentials */                                      \
 /* uid etc */  0,0,0,0,0,0,0,0,                                \
 /* suppl grps*/ 0, {0,},                                       \
-/* caps */      CAP_FULL_SET, CAP_FULL_SET, CAP_FULL_SET,    \
+/* caps */      CAP_INIT_EFF_SET,CAP_INIT_INH_SET,CAP_FULL_SET, \
 /* rlimits */   INIT_RLIMITS, \
 /* math */     0, \
 /* comm */     "swapper", \
index 30fe3123980416b172568798b283bd9a922d3384..e505bcc0168430d1c5f94835ed6f7c9bb38f2012 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -477,9 +477,10 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
        case IPC_SET:
                err = -EPERM;
                if (current->euid != ipcp->cuid && 
-                   current->euid != ipcp->uid && !suser())
+                   current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
+                   /* We _could_ check for CAP_CHOWN above, but we don't */
                        goto out;
-               if (tbuf.msg_qbytes > MSGMNB && !suser())
+               if (tbuf.msg_qbytes > MSGMNB && !capable(CAP_SYS_RESOURCE))
                        goto out;
                msq->msg_qbytes = tbuf.msg_qbytes;
                ipcp->uid = tbuf.msg_perm.uid;
@@ -492,7 +493,7 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
        case IPC_RMID:
                err = -EPERM;
                if (current->euid != ipcp->cuid && 
-                   current->euid != ipcp->uid && !suser())
+                   current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
                        goto out;
 
                freeque (id); 
index 8e5be61d291fff793e97a78369acc86bce87995f..0ab5785846979f8c47138d97a217dfd70c29d5d7 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -482,7 +482,8 @@ asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                        goto out;
                break;
        case IPC_RMID:
-               if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) {
+               if (current->euid == ipcp->cuid || 
+                   current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
                        freeary (id);
                        err = 0;
                        goto out;
@@ -540,7 +541,8 @@ asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg)
                update_queue(sma);
                break;
        case IPC_SET:
-               if (current->euid == ipcp->cuid || current->euid == ipcp->uid || suser()) {
+               if (current->euid == ipcp->cuid || 
+                   current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) {
                        ipcp->uid = tbuf.sem_perm.uid;
                        ipcp->gid = tbuf.sem_perm.gid;
                        ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
index 09b69c4a3388a61350195144e63f8696cd4704fb..0962be88279e716b5ef74ae3b7c6af811597d2bd 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -306,7 +306,7 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
        switch (cmd) {
        case SHM_UNLOCK:
                err = -EPERM;
-               if (!suser())
+               if (!capable(CAP_IPC_LOCK))
                        goto out;
                err = -EINVAL;
                if (!(ipcp->mode & SHM_LOCKED))
@@ -318,7 +318,7 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
 /* Should the pages be faulted in here or leave it to user? */
 /* need to determine interaction with current->swappable */
                err = -EPERM;
-               if (!suser())
+               if (!capable(CAP_IPC_LOCK))
                        goto out;
                err = -EINVAL;
                if (ipcp->mode & SHM_LOCKED)
@@ -347,7 +347,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
                break;
        case IPC_SET:
                if (current->euid == shp->shm_perm.uid ||
-                   current->euid == shp->shm_perm.cuid || suser()) {
+                   current->euid == shp->shm_perm.cuid || 
+                   capable(CAP_SYS_ADMIN)) {
                        ipcp->uid = tbuf.shm_perm.uid;
                        ipcp->gid = tbuf.shm_perm.gid;
                        ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
@@ -359,7 +360,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf)
                goto out;
        case IPC_RMID:
                if (current->euid == shp->shm_perm.uid ||
-                   current->euid == shp->shm_perm.cuid || suser()) {
+                   current->euid == shp->shm_perm.cuid || 
+                   capable(CAP_SYS_ADMIN)) {
                        shp->shm_perm.mode |= SHM_DEST;
                        if (shp->shm_nattch <= 0)
                                killseg (id);
index eacea2b6239d286d59bb099087984a7cfdd68a8d..fe13f8676553ffc5bc1fa9415114e1028da83c2e 100644 (file)
@@ -47,8 +47,10 @@ int ipcperms (struct ipc_perm *ipcp, short flag)
        else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
                granted_mode >>= 3;
        /* is there some bit set in requested_mode but not in granted_mode? */
-       if ((requested_mode & ~granted_mode & 0007) && !suser())
+       if ((requested_mode & ~granted_mode & 0007) && 
+           !capable(CAP_IPC_OWNER))
                return -1;
+
        return 0;
 }
 
index 4e0a1d87d8f523f4780ccb4e941f03c6a0de03f0..abd520d4499d51a6eb283e4e686bb73bf488a5b5 100644 (file)
@@ -13,7 +13,7 @@
 O_TARGET := kernel.o
 O_OBJS    = sched.o dma.o fork.o exec_domain.o panic.o printk.o sys.o \
            module.o exit.o itimer.o info.o time.o softirq.o resource.o \
-           sysctl.o acct.o
+           sysctl.o acct.o capability.o
 
 OX_OBJS  += signal.o
 
index 4229b9ebfb5c87276cebc6ac83263e84d9388008..6a00f35711771ed821611cc8c56c73342fa65ab2 100644 (file)
@@ -119,7 +119,7 @@ asmlinkage int sys_acct(const char *name)
        int error = -EPERM;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_PACCT))
                goto out;
 
        if (name == (char *)NULL) {
diff --git a/kernel/capability.c b/kernel/capability.c
new file mode 100644 (file)
index 0000000..ddbfaa8
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * linux/kernel/capability.c
+ *
+ * Copyright (C) 1997  Andrew Main <zefram@fysh.org>
+ * Integrated into 2.1.97+,  Andrew G. Morgan <morgan@transmeta.com>
+ */ 
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/capability.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+
+#include <asm/uaccess.h>
+
+static inline void cap_fromuser(kernel_cap_t *k, __u32 *u)
+{
+     copy_from_user(k, u, sizeof(*k));
+}
+
+
+static inline void cap_touser(__u32 *u, const kernel_cap_t *k)
+{
+     copy_to_user(u, k, sizeof(*k));
+}
+
+#ifdef __SMP__
+static spinlock_t task_capability_lock;
+#endif
+
+/*
+ * For sys_getproccap() and sys_setproccap(), any of the three
+ * capability set pointers may be NULL -- indicating that that set is
+ * uninteresting and/or not to be changed.
+ */
+
+asmlinkage int sys_capget(cap_user_header_t header, cap_user_data_t data)
+{
+     int error = -EINVAL, pid;
+     __u32 version;
+     struct task_struct *target;
+
+     if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) {
+             /* not large enough for current header so indicate error */
+             if (access_ok(VERIFY_WRITE, &header->version,
+                           sizeof(header->version))) {
+                     return error;
+             }
+             goto all_done;
+     }
+
+     copy_from_user(&version, &header->version, sizeof(header->version));
+     if (version != _LINUX_CAPABILITY_VERSION) {
+             /* if enough space for kernel version, write that */
+
+     all_done:
+             version = _LINUX_CAPABILITY_VERSION;
+             copy_to_user(&header->version, &version,
+                          sizeof(header->version));
+             return error;
+     }
+
+     if (!access_ok(VERIFY_WRITE, data, sizeof(*data))) {
+             return error;
+     }
+
+     copy_from_user(&pid, &header->pid, sizeof(header->pid));
+     if (pid < 0) {
+             return error;
+     }
+
+     spin_lock(&task_capability_lock);
+
+     if (pid && pid != current->pid) {
+             read_lock(&tasklist_lock);
+             target = find_task_by_pid(pid);  /* identify target of query */
+             if (!target) {
+                     error = -ESRCH;
+                     goto out;
+             }
+     } else {
+             target = current;
+     }
+
+     cap_touser(&data->permitted, &target->cap_permitted);
+     cap_touser(&data->inheritable, &target->cap_inheritable);
+     cap_touser(&data->effective, &target->cap_effective);
+
+     error = 0;
+
+out:
+     if (target != current) {
+             read_unlock(&tasklist_lock);
+     }
+     spin_unlock(&task_capability_lock);
+     return error;
+}
+
+/* set capabilities for all processes in a given process group */
+
+static void cap_set_pg(int pgrp,
+                    kernel_cap_t *effective,
+                    kernel_cap_t *inheritable,
+                    kernel_cap_t *permitted)
+{
+     struct task_struct *target;
+
+     /* FIXME: do we need to have a write lock here..? */
+     read_lock(&tasklist_lock);
+     for_each_task(target) {
+             if (target->pgrp != pgrp)
+                     continue;
+             target->cap_effective   = *effective;
+             target->cap_inheritable = *inheritable;
+             target->cap_permitted   = *permitted;
+     }
+     read_unlock(&tasklist_lock);
+}
+
+/* set capabilities for all processes other than 1 and self */
+
+static void cap_set_all(kernel_cap_t *effective,
+                     kernel_cap_t *inheritable,
+                     kernel_cap_t *permitted)
+{
+     struct task_struct *target;
+
+     /* FIXME: do we need to have a write lock here..? */
+     read_lock(&tasklist_lock);
+     /* ALL means everyone other than self or 'init' */
+     for_each_task(target) {
+             if (target == current || target->pid == 1)
+                     continue;
+             target->cap_effective   = *effective;
+             target->cap_inheritable = *inheritable;
+             target->cap_permitted   = *permitted;
+     }
+     read_unlock(&tasklist_lock);
+}
+
+/*
+ * The restrictions on setting capabilities are specified as:
+ *
+ * [pid is for the 'target' task.  'current' is the calling task.]
+ *
+ * I: any raised capabilities must be a subset of the (old current) Permitted
+ * P: any raised capabilities must be a subset of the (old current) permitted
+ * E: must be set to a subset of (new target) Permitted
+ */
+
+asmlinkage int sys_capset(cap_user_header_t header, const cap_user_data_t data)
+{
+     kernel_cap_t inheritable, permitted, effective;
+     __u32 version;
+     struct task_struct *target;
+     int error = -EINVAL, pid;
+
+     if (!access_ok(VERIFY_WRITE, &header->version, sizeof(*header))) {
+             /* not large enough for current header so indicate error */
+             if (!access_ok(VERIFY_WRITE, &header->version,
+                            sizeof(header->version))) {
+                     return error;
+             }
+             goto all_done;
+     }
+
+     copy_from_user(&version, &header->version, sizeof(header->version));
+     if (version != _LINUX_CAPABILITY_VERSION) {
+
+     all_done:
+             version = _LINUX_CAPABILITY_VERSION;
+             copy_to_user(&header->version, &version,
+                          sizeof(header->version));
+             return error;
+     }
+
+     if (!access_ok(VERIFY_READ, data, sizeof(*data))) {
+             return error;
+     }
+
+     /* may want to set other processes at some point -- for now demand 0 */
+     copy_from_user(&pid, &header->pid, sizeof(pid));
+
+     error = -EPERM;
+     if (pid && !capable(CAP_SETPCAP))
+             return error;
+
+     spin_lock(&task_capability_lock);
+
+     if (pid > 0 && pid != current->pid) {
+             read_lock(&tasklist_lock);
+             target = find_task_by_pid(pid);  /* identify target of query */
+             if (!target) {
+                     error = -ESRCH;
+                     goto out;
+             }
+     } else {
+             target = current;
+     }
+
+     /* copy from userspace */
+     cap_fromuser(&effective, &data->effective);
+     cap_fromuser(&inheritable, &data->inheritable);
+     cap_fromuser(&permitted, &data->permitted);
+
+     /* verify restrictions on target's new Inheritable set */
+     if (!cap_issubset(inheritable,
+                       cap_combine(target->cap_inheritable,
+                                   current->cap_permitted))) {
+             goto out;
+     }
+
+     /* verify restrictions on target's new Permitted set */
+     if (!cap_issubset(permitted,
+                       cap_combine(target->cap_permitted,
+                                   current->cap_permitted))) {
+             goto out;
+     }
+
+     /* verify the _new_Effective_ is a subset of the _new_Permitted_ */
+     if (!cap_issubset(effective, permitted)) {
+             goto out;
+     }
+
+     /* having verified that the proposed changes are legal,
+           we now put them into effect. */
+     error = 0;
+
+     if (pid < 0) {
+             if (pid == -1)  /* all procs other than current and init */
+                     cap_set_all(&effective, &inheritable, &permitted);
+
+             else            /* all procs in process group */
+                     cap_set_pg(-pid, &effective, &inheritable, &permitted);
+             goto spin_out;
+     } else {
+             /* FIXME: do we need to have a write lock here..? */
+             target->cap_effective   = effective;
+             target->cap_inheritable = inheritable;
+             target->cap_permitted   = permitted;
+     }
+
+out:
+     if (target != current) {
+             read_unlock(&tasklist_lock);
+     }
+spin_out:
+     spin_unlock(&task_capability_lock);
+     return error;
+}
index 88199cae15360d38a707e280e1c7a5c62ffbcf42..c29c52eceec09968e6c6050814b45279cdfe70f1 100644 (file)
@@ -56,9 +56,7 @@ static struct uid_taskcount {
        int task_count;
 } *uidhash[UIDHASH_SZ];
 
-#ifdef __SMP__
-static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;
-#endif
+spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;
 
 kmem_cache_t *uid_cachep;
 
@@ -154,10 +152,8 @@ static inline int find_empty_process(void)
        return -EAGAIN;
 }
 
-#ifdef __SMP__
 /* Protects next_safe and last_pid. */
-static spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
-#endif
+spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
 
 static int get_pid(unsigned long flags)
 {
index ffd73ef85a158b5ccbe4ed19eced20d2a3fc1989..ecba758feeb878c9a3e15a2d04cb1cef4ab6fde9 100644 (file)
@@ -120,7 +120,7 @@ sys_create_module(const char *name_user, size_t size)
        struct module *mod;
 
        lock_kernel();
-       if (!suser()) {
+       if (!capable(CAP_SYS_MODULE)) {
                error = -EPERM;
                goto err0;
        }
@@ -175,7 +175,7 @@ sys_init_module(const char *name_user, struct module *mod_user)
        struct module_ref *dep;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_MODULE))
                goto err0;
        if ((namelen = get_mod_name(name_user, &name)) < 0) {
                error = namelen;
@@ -366,7 +366,7 @@ sys_delete_module(const char *name_user)
        int something_changed;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_MODULE))
                goto out;
 
        if (name_user) {
index 48922d7795e448e267a2ecb6e989a5d6360ef4c7..9060da3ef2822d7d8a857c20d44bda3d5d551cc0 100644 (file)
@@ -130,7 +130,7 @@ asmlinkage int sys_syslog(int type, char * buf, int len)
        int error = -EPERM;
 
        lock_kernel();
-       if ((type != 3) && !suser())
+       if ((type != 3) && !capable(CAP_SYS_ADMIN))
                goto out;
        error = 0;
        switch (type) {
index f9246e78533be29af1c4e865bdd986be386d66a3..af68649ef0706aee48bae47af2c9d3df73be0483 100644 (file)
@@ -1227,7 +1227,7 @@ asmlinkage int sys_nice(int increment)
         
        newprio = increment;
        if (increment < 0) {
-               if (!suser())
+               if (!capable(CAP_SYS_NICE))
                        return -EPERM;
                newprio = -increment;
                increase = 1;
@@ -1322,10 +1322,11 @@ static int setscheduler(pid_t pid, int policy,
                goto out_unlock;
 
        retval = -EPERM;
-       if ((policy == SCHED_FIFO || policy == SCHED_RR) && !suser())
+       if ((policy == SCHED_FIFO || policy == SCHED_RR) && 
+           !capable(CAP_SYS_NICE))
                goto out_unlock;
        if ((current->euid != p->euid) && (current->euid != p->uid) &&
-           !suser())
+           !capable(CAP_SYS_NICE))
                goto out_unlock;
 
        retval = 0;
index eccb06614d3094e8345d2d3e6d7815b3689d119a..ca34cecbf6c531f7d1af65fb0154dd414b8ab1e2 100644 (file)
@@ -235,7 +235,7 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
            && ((sig != SIGCONT) || (current->session != t->session))
            && (current->euid ^ t->suid) && (current->euid ^ t->uid)
            && (current->uid ^ t->suid) && (current->uid ^ t->uid)
-           && !suser())
+           && !capable(CAP_SYS_ADMIN))
                goto out_nolock;
 
        /* The null signal is a permissions and process existance probe.
index aadb3ab5fc1a5f868e87cf9a5339250abe056e8e..1de75c366b56bf7d9760bf311db6fd148a21216f 100644 (file)
@@ -114,13 +114,13 @@ asmlinkage int sys_setpriority(int which, int who, int niceval)
                if (!proc_sel(p, which, who))
                        continue;
                if (p->uid != current->euid &&
-                       p->uid != current->uid && !suser()) {
+                       p->uid != current->uid && !capable(CAP_SYS_NICE)) {
                        error = EPERM;
                        continue;
                }
                if (error == ESRCH)
                        error = 0;
-               if (priority > p->priority && !suser())
+               if (priority > p->priority && !capable(CAP_SYS_NICE))
                        error = EACCES;
                else
                        p->priority = priority;
@@ -172,7 +172,7 @@ asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg)
        char buffer[256];
 
        /* We only trust the superuser with rebooting the system. */
-       if (!suser())
+       if (!capable(CAP_SYS_BOOT))
                return -EPERM;
 
        /* For safety, we require "magic" arguments. */
@@ -273,7 +273,7 @@ asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
        if (rgid != (gid_t) -1) {
                if ((old_rgid == rgid) ||
                    (current->egid==rgid) ||
-                   suser())
+                   capable(CAP_SETGID))
                        current->gid = rgid;
                else
                        return -EPERM;
@@ -282,7 +282,7 @@ asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
                if ((old_rgid == egid) ||
                    (current->egid == egid) ||
                    (current->sgid == egid) ||
-                   suser())
+                   capable(CAP_SETGID))
                        current->fsgid = current->egid = egid;
                else {
                        current->gid = old_rgid;
@@ -307,7 +307,7 @@ asmlinkage int sys_setgid(gid_t gid)
 {
        int old_egid = current->egid;
 
-       if (suser())
+       if (capable(CAP_SETGID))
                current->gid = current->egid = current->sgid = current->fsgid = gid;
        else if ((gid == current->gid) || (gid == current->sgid))
                current->egid = current->fsgid = gid;
@@ -319,6 +319,41 @@ asmlinkage int sys_setgid(gid_t gid)
        return 0;
 }
   
+/* 
+ * cap_emulate_setxuid() fixes the effective / permitted capabilities of
+ * a process after a call to setuid, setreuid, or setresuid.
+ *
+ *  1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
+ *  {r,e,s}uid != 0, the permitted and effective capabilities are
+ *  cleared.
+ *
+ *  2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
+ *  capabilities of the process are cleared.
+ *
+ *  3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
+ *  capabilities are set to the permitted capabilities.
+ *
+ *  fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 
+ *  never happen.
+ *
+ *  -astor 
+ */
+extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, 
+                                      int old_suid)
+{
+       if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
+           (current->uid != 0 && current->euid != 0 && current->suid != 0)) {
+               cap_clear(current->cap_permitted);
+               cap_clear(current->cap_effective);
+       }
+       if (old_euid == 0 && current->euid != 0) {
+               cap_clear(current->cap_effective);
+       }
+       if (old_euid != 0 && current->euid == 0) {
+               current->cap_effective = current->cap_permitted;
+       }
+}
+
 /*
  * Unprivileged users may change the real uid to the effective uid
  * or vice versa.  (BSD-style)
@@ -336,14 +371,15 @@ asmlinkage int sys_setgid(gid_t gid)
  */
 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
 {
-       int old_ruid, old_euid, new_ruid;
+       int old_ruid, old_euid, old_suid, new_ruid;
 
        new_ruid = old_ruid = current->uid;
        old_euid = current->euid;
+       old_suid = current->suid;
        if (ruid != (uid_t) -1) {
                if ((old_ruid == ruid) || 
                    (current->euid==ruid) ||
-                   suser())
+                   capable(CAP_SETUID))
                        new_ruid = ruid;
                else
                        return -EPERM;
@@ -352,7 +388,7 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
                if ((old_ruid == euid) ||
                    (current->euid == euid) ||
                    (current->suid == euid) ||
-                   suser())
+                   capable(CAP_SETUID))
                        current->fsuid = current->euid = euid;
                else
                        return -EPERM;
@@ -375,9 +411,16 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
                if(new_ruid)
                        charge_uid(current, 1);
        }
+       
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               cap_emulate_setxuid(old_ruid, old_euid, old_suid);
+       }
+
        return 0;
 }
 
+
+               
 /*
  * setuid() is implemented like SysV w/ SAVED_IDS 
  * 
@@ -392,10 +435,11 @@ asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
 asmlinkage int sys_setuid(uid_t uid)
 {
        int old_euid = current->euid;
-       int old_ruid, new_ruid;
+       int old_ruid, old_suid, new_ruid;
 
        old_ruid = new_ruid = current->uid;
-       if (suser())
+       old_suid = current->suid;
+       if (capable(CAP_SETUID))
                new_ruid = current->euid = current->suid = current->fsuid = uid;
        else if ((uid == current->uid) || (uid == current->suid))
                current->fsuid = current->euid = uid;
@@ -412,6 +456,11 @@ asmlinkage int sys_setuid(uid_t uid)
                if(new_ruid)
                        charge_uid(current, 1);
        }
+
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               cap_emulate_setxuid(old_ruid, old_euid, old_suid);
+       }
+
        return 0;
 }
 
@@ -422,6 +471,9 @@ asmlinkage int sys_setuid(uid_t uid)
  */
 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
+       int old_ruid = current->uid;
+       int old_euid = current->euid;
+       int old_suid = current->suid;
        if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
                if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
                    (ruid != current->euid) && (ruid != current->suid))
@@ -448,6 +500,11 @@ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        }
        if (suid != (uid_t) -1)
                current->suid = suid;
+
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               cap_emulate_setxuid(old_ruid, old_euid, old_suid);
+       }
+
        return 0;
 }
 
@@ -515,11 +572,31 @@ asmlinkage int sys_setfsuid(uid_t uid)
 
        old_fsuid = current->fsuid;
        if (uid == current->uid || uid == current->euid ||
-           uid == current->suid || uid == current->fsuid || suser())
+           uid == current->suid || uid == current->fsuid || 
+           capable(CAP_SETUID))
                current->fsuid = uid;
        if (current->fsuid != old_fsuid)
                current->dumpable = 0;
 
+       /* We emulate fsuid by essentially doing a scaled-down version
+         * of what we did in setresuid and friends. However, we only
+         * operate on the fs-specific bits of the process' effective
+         * capabilities 
+         *
+         * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
+         *          if not, we might be a bit too harsh here.
+         */
+       
+       if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+               if (old_fsuid == 0 && current->fsuid != 0) {
+                       current->cap_effective.cap &= ~CAP_FS_MASK;
+               }
+               if (old_fsuid != 0 && current->fsuid == 0) {
+                       current->cap_effective.cap |=
+                               (current->cap_permitted.cap & CAP_FS_MASK);
+               }
+       }
+
        return old_fsuid;
 }
 
@@ -532,7 +609,8 @@ asmlinkage int sys_setfsgid(gid_t gid)
 
        old_fsgid = current->fsgid;
        if (gid == current->gid || gid == current->egid ||
-           gid == current->sgid || gid == current->fsgid || suser())
+           gid == current->sgid || gid == current->fsgid || 
+           capable(CAP_SETGID))
                current->fsgid = gid;
        if (current->fsgid != old_fsgid)
                current->dumpable = 0;
@@ -716,7 +794,7 @@ asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
  
 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
-       if (!suser())
+       if (!capable(CAP_SETGID))
                return -EPERM;
        if ((unsigned) gidsetsize > NGROUPS)
                return -EINVAL;
@@ -756,7 +834,7 @@ asmlinkage int sys_newuname(struct new_utsname * name)
 
 asmlinkage int sys_sethostname(char *name, int len)
 {
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
@@ -787,7 +865,7 @@ asmlinkage int sys_gethostname(char *name, int len)
  */
 asmlinkage int sys_setdomainname(char *name, int len)
 {
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
        if (len < 0 || len > __NEW_UTS_LEN)
                return -EINVAL;
@@ -820,7 +898,7 @@ asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
        old_rlim = current->rlim + resource;
        if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
             (new_rlim.rlim_max > old_rlim->rlim_max)) &&
-           !suser())
+           !capable(CAP_SYS_RESOURCE))
                return -EPERM;
        if (resource == RLIMIT_NOFILE) {
                if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
@@ -916,3 +994,4 @@ asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
         }
         return error;
 }
+
index e16a7a15007ff7a064f3b0145677c5ad0f69e827..ff3a5d6843d183de57a052d73c2d2d6b2fd0b796 100644 (file)
@@ -87,7 +87,7 @@ asmlinkage int sys_stime(int * tptr)
 {
        int value;
 
-       if (!suser())
+       if (!capable(CAP_SYS_TIME))
                return -EPERM;
        if (get_user(value, tptr))
                return -EFAULT;
@@ -156,7 +156,7 @@ int do_sys_settimeofday(struct timeval *tv, struct timezone *tz)
 {
        static int firsttime = 1;
 
-       if (!suser())
+       if (!capable(CAP_SYS_TIME))
                return -EPERM;
                
        if (tz) {
@@ -221,7 +221,7 @@ int do_adjtimex(struct timex *txc)
         long ltemp, mtemp, save_adjust;
 
        /* In order to modify anything, you gotta be super-user! */
-       if (txc->modes && !suser())
+       if (txc->modes && !capable(CAP_SYS_TIME))
                return -EPERM;
                
        /* Now we validate the data before disabling interrupts */
index 5bffab93f0b6400e60b7b562dee48f1c1151db32..3a322f8a540cd43e734c1602cef64fb54933ab8a 100644 (file)
@@ -144,7 +144,7 @@ static int do_mlock(unsigned long start, size_t len, int on)
        struct vm_area_struct * vma, * next;
        int error;
 
-       if (!suser())
+       if (!capable(CAP_IPC_LOCK))
                return -EPERM;
        len = (len + ~PAGE_MASK) & PAGE_MASK;
        end = start + len;
@@ -235,7 +235,7 @@ static int do_mlockall(int flags)
        unsigned int def_flags;
        struct vm_area_struct * vma;
 
-       if (!suser())
+       if (!capable(CAP_IPC_LOCK))
                return -EPERM;
 
        def_flags = 0;
index d8b78d73afbdeee885fb21159c4aa204cae8f930..339e11470463d0569572646d8a184bfc89d15064 100644 (file)
@@ -98,9 +98,7 @@ static inline void remove_mem_queue(struct page * entry)
  *
  * Hint: -mask = 1+~mask
  */
-#ifdef __SMP__
-static spinlock_t page_alloc_lock;
-#endif
+static spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This routine is used by the kernel swap deamon to determine
index f9cd0d47e852f422618704552754ce62c4cbb544..1a27f266a67cc7627bb1eb6d95e5344f1778aa55 100644 (file)
@@ -356,7 +356,7 @@ asmlinkage int sys_swapoff(const char * specialfile)
        int err = -EPERM;
        
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                goto out;
 
        dentry = namei(specialfile);
@@ -491,7 +491,7 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        static int least_priority = 0;
 
        lock_kernel();
-       if (!suser())
+       if (!capable(CAP_SYS_ADMIN))
                goto out;
        memset(&filp, 0, sizeof(filp));
        p = swap_info;
index c56adc148b2c4d7a6633c6e5122e7b0cc9d32f91..b85835f475aebd004b5b778d6980e546409ad8a7 100644 (file)
@@ -719,7 +719,7 @@ int atif_ioctl(int cmd, void *arg)
        switch(cmd)
        {
                case SIOCSIFADDR:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return (-EPERM);
                        if(sa->sat_family != AF_APPLETALK)
                                return (-EINVAL);
@@ -830,7 +830,7 @@ int atif_ioctl(int cmd, void *arg)
 
                case SIOCATALKDIFADDR:
                case SIOCDIFADDR:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return (-EPERM);
                        if(sa->sat_family != AF_APPLETALK)
                                return (-EINVAL);
@@ -1809,7 +1809,7 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
                 */
                case SIOCADDRT:
                case SIOCDELRT:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return -EPERM;
                        return (atrtr_ioctl(cmd,(void *)arg));
 
index 1bb5dede15e2dd1b4af41a5ea8228e5623adff2c..69315d9483cf7c952c70a27b01a4337ce3e3a42c 100644 (file)
@@ -321,7 +321,7 @@ struct device *dev_alloc(const char *name, int *err)
 
 void dev_load(const char *name)
 {
-       if(!dev_get(name) && suser())
+       if(!dev_get(name) && capable(CAP_SYS_MODULE))
                request_module(name);
 }
 
@@ -1591,7 +1591,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
                case SIOCDELMULTI:
                case SIOCSIFHWBROADCAST:
                case SIOCSIFTXQLEN:
-                       if (!suser())
+                       if (!capable(CAP_NET_ADMIN))
                                return -EPERM;
                        dev_load(ifr.ifr_name);
                        rtnl_lock();
index ac4aefda03eb524d609f71506d4c4f5cbcaf937f..dd19cf5e0a969f99b29d2c38570b020513175f4c 100644 (file)
 
 static __inline__ int scm_check_creds(struct ucred *creds)
 {
-       /* N.B. The test for suser should follow the credential check */
-       if (suser())
+       if ((creds->pid == current->pid || capable(CAP_SYS_ADMIN)) &&
+           ((creds->uid == current->uid || creds->uid == current->euid ||
+             creds->uid == current->suid) || capable(CAP_SETUID)) &&
+           ((creds->gid == current->gid || creds->gid == current->egid ||
+             creds->gid == current->sgid) || capable(CAP_SETGID))) {
                return 0;
-       if (creds->pid != current->pid ||
-           (creds->uid != current->uid && creds->uid != current->euid &&
-            creds->uid != current->suid) ||
-           (creds->gid != current->gid && creds->gid != current->egid &&
-            creds->gid != current->sgid))
-               return -EPERM;
-       return 0;
+       }
+       return -EPERM;
 }
 
-
 static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
 {
        int *fdp = (int*)CMSG_DATA(cmsg);
index 30e5d3e77d09bb02984524748942bff2659a1884..428b4052c315856ee6898e94398d0063f1b9f015 100644 (file)
@@ -185,7 +185,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
        switch(optname) 
        {
                case SO_DEBUG:  
-                       if(val && !suser())
+                       if(val && !capable(CAP_NET_ADMIN))
                        {
                                ret = -EACCES;
                        }
@@ -924,7 +924,7 @@ int sock_no_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
                         */
                        if (current->pgrp != -arg &&
                                current->pid != arg &&
-                               !suser()) return(-EPERM);
+                               !capable(CAP_NET_ADMIN)) return(-EPERM);
                        sk->proc = arg;
                        return(0);
                case F_GETOWN:
index bba2bb96555d181de9a7bd9a4bb2b6051d6010d4..d711075194bca1b895e0aabf5326ac92af136e36 100644 (file)
@@ -374,7 +374,7 @@ static int inet_create(struct socket *sock, int protocol)
                sock->ops = &inet_dgram_ops;
                break;
        case SOCK_RAW:
-               if (!suser())
+               if (!capable(CAP_NET_RAW))
                        goto free_and_badperm;
                if (!protocol)
                        goto free_and_noproto;
@@ -521,7 +521,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 #endif          
        if (snum == 0) 
                snum = sk->prot->good_socknum();
-       if (snum < PROT_SOCK && !suser())
+       if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
                return(-EACCES);
        
        chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
@@ -529,7 +529,7 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
            chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
                /* Superuser may bind to any address to allow transparent proxying. */
-               if(chk_addr_ret != RTN_UNICAST || !suser())
+               if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
 #endif
                        return -EADDRNOTAVAIL;  /* Source address MUST be ours! */
        }
@@ -868,7 +868,8 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        err = get_user(pid, (int *) arg);
                        if (err)
                                return err; 
-                       if (current->pid != pid && current->pgrp != -pid && !suser())
+                       if (current->pid != pid && current->pgrp != -pid && 
+                           !capable(CAP_NET_ADMIN))
                                return -EPERM;
                        sk->proc = pid;
                        return(0);
index 425885cc2d61975ee2107d30ecee26cf85cfb5c7..63760de8033f9f2f30baa3ccb121d6333557437d 100644 (file)
@@ -435,7 +435,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
                break;
 
        case SIOCSIFFLAGS:
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EACCES;
                rtnl_lock();
                exclusive = 1;
@@ -444,7 +444,7 @@ int devinet_ioctl(unsigned int cmd, void *arg)
        case SIOCSIFBRDADDR:    /* Set the broadcast address */
        case SIOCSIFDSTADDR:    /* Set the destination address */
        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EACCES;
                if (sin->sin_family != AF_INET)
                        return -EINVAL;
index 6350a6366006fc30714c0cfcb34ce632dc1ce387..24f3052fef857e04ce59098a3d0140e92d8be9d0 100644 (file)
@@ -253,7 +253,7 @@ int ip_rt_ioctl(unsigned int cmd, void *arg)
        switch (cmd) {
        case SIOCADDRT:         /* Add a route */
        case SIOCDELRT:         /* Delete a route */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                if (copy_from_user(&r, arg, sizeof(struct rtentry)))
                        return -EFAULT;
index f60c206a0ad7ce01734a4a6dabf7226948f13f4a..c2598eb96bc4d5060ee541dc80b03efdef408035 100644 (file)
@@ -311,7 +311,8 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                          /* Reject setting of unused bits */
                        if (val & ~(IPTOS_TOS_MASK|IPTOS_PREC_MASK))
                                return -EINVAL;
-                       if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && !suser())
+                       if (IPTOS_PREC(val) >= IPTOS_PREC_CRITIC_ECP && 
+                           !capable(CAP_NET_ADMIN))
                                return -EPERM;
                        if (sk->ip_tos != val) {
                                sk->ip_tos=val;
@@ -453,7 +454,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                case IP_FW_POLICY_OUT:
                case IP_FW_POLICY_FWD:
                case IP_FW_MASQ_TIMEOUTS:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return -EACCES;
                        if(optlen>sizeof(tmp_fw) || optlen<1)
                                return -EINVAL;
@@ -467,7 +468,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                case IP_FW_MASQ_ADD:
                case IP_FW_MASQ_DEL:
                case IP_FW_MASQ_FLUSH:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return -EPERM;
                        if(optlen>sizeof(masq_ctl) || optlen<1)
                                return -EINVAL;
@@ -483,7 +484,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                case IP_ACCT_DELETE:
                case IP_ACCT_FLUSH:
                case IP_ACCT_ZERO:
-                       if(!suser())
+                       if(!capable(CAP_NET_ADMIN))
                                return -EACCES;
                        if(optlen>sizeof(tmp_fw) || optlen<1)
                                return -EINVAL;
index 735d06d4464012dd325649dd5c46792825a65645..f26df1442ab6630326649963de2d24cd0dd787d1 100644 (file)
@@ -398,7 +398,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
           chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) {
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
                /* Superuser may bind to any address to allow transparent proxying. */
-               if(chk_addr_ret != RTN_UNICAST || !suser())
+               if(chk_addr_ret != RTN_UNICAST || !capable(CAP_NET_ADMIN))
 #endif
                        return -EADDRNOTAVAIL;
        }
index 80e40b49faaa87cd352ac6d04afc8202bc1f8098..d9dfa8e76c843966574ba4f6e0b12c8d164258a4 100644 (file)
@@ -646,7 +646,7 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
 #ifdef CONFIG_IP_TRANSPARENT_PROXY
        if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_PROXY|MSG_NOSIGNAL))
                return -EINVAL;
-       if ((msg->msg_flags&MSG_PROXY) && !suser() )
+       if ((msg->msg_flags&MSG_PROXY) && !capable(CAP_NET_ADMIN))
                return -EPERM;
 #else
        if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT|MSG_NOSIGNAL))
index 0241e04590721e6c998d05c010b982c9bf66f98a..5571c04c7bbe8d5b1b1076a12df531841e13e668 100644 (file)
@@ -894,7 +894,7 @@ int addrconf_add_ifaddr(void *arg)
        struct in6_ifreq ireq;
        int err;
        
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
                return -EPERM;
        
        if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -911,7 +911,7 @@ int addrconf_del_ifaddr(void *arg)
        struct in6_ifreq ireq;
        int err;
        
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
                return -EPERM;
 
        if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
index 902274ecb80e2199e1d391fdea74a6b06f2b1de2..c1b2e9d14b4e44f771c71466530d6af61410f3e2 100644 (file)
@@ -89,7 +89,7 @@ static int inet6_create(struct socket *sock, int protocol)
                prot=&udpv6_prot;
                sock->ops = &inet6_dgram_ops;
        } else if(sock->type == SOCK_RAW) {
-               if (!suser()) 
+               if (!capable(CAP_NET_RAW))
                        goto free_and_badperm;
                if (!protocol) 
                        goto free_and_noproto;
@@ -187,7 +187,7 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        snum = ntohs(addr->sin6_port);
        if (snum == 0) 
                snum = sk->prot->good_socknum();
-       if (snum < PROT_SOCK && !suser()) 
+       if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
                return(-EACCES);
        
        addr_type = ipv6_addr_type(&addr->sin6_addr);
@@ -291,7 +291,8 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        return err;
 
                /* see sock_no_fcntl */
-               if (current->pid != pid && current->pgrp != -pid && !suser())
+               if (current->pid != pid && current->pgrp != -pid && 
+                   !capable(CAP_NET_ADMIN))
                        return -EPERM;
                sk->proc = pid;
                return(0);
index a71c9c0e583315b54d207dd74ebc38bf270bac7d..3baa410076eb71f6b8c070d711e21c8f8f61901c 100644 (file)
@@ -1379,7 +1379,7 @@ int ipv6_route_ioctl(unsigned int cmd, void *arg)
        switch(cmd) {
        case SIOCADDRT:         /* Add a route */
        case SIOCDELRT:         /* Delete a route */
-               if (!suser())
+               if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
                err = copy_from_user(&rtmsg, arg,
                                     sizeof(struct in6_rtmsg));
index 858ea0e73f1f4cd8c6849196a9468c6946b9ed0d..f56b660c0df2908c1b3ee48469bfb9b91796a021 100644 (file)
@@ -691,7 +691,7 @@ static int packet_create(struct socket *sock, int protocol)
        struct sock *sk;
        int err;
 
-       if (!suser())
+       if (!capable(CAP_NET_RAW))
                return -EPERM;
        if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW
 #ifdef CONFIG_SOCK_PACKET
@@ -1089,7 +1089,8 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
                        err = get_user(pid, (int *) arg);
                        if (err)
                                return err; 
-                       if (current->pid != pid && current->pgrp != -pid && !suser())
+                       if (current->pid != pid && current->pgrp != -pid && 
+                           !capable(CAP_NET_ADMIN))
                                return -EPERM;
                        sk->proc = pid;
                        return(0);
index 286a2aa6811c59fc3eae238efdb503f32a60649a..494b9fa624a0093394e2b5062c151619a0ecb901 100644 (file)
@@ -1193,7 +1193,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                case SIOCADDRT:
                case SIOCDELRT:
                case SIOCRSCLRRT:
-                       if (!suser()) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
                        return rose_rt_ioctl(cmd, (void *)arg);
 
                case SIOCRSGCAUSE: {
index 30e2c2034bda2d9cd3b8bf1f004d3014489143a9..b00d0ab2ae4ca83b279fde1745858250e950b159 100644 (file)
@@ -371,7 +371,7 @@ int wanrouter_ioctl(struct inode* inode, struct file* file,
        struct proc_dir_entry* dent;
        wan_device_t* wandev;
 
-       if (!suser())
+       if (!capable(CAP_NET_ADMIN))
                return -EPERM;
                
        if ((cmd >> 8) != ROUTER_IOCTL)
index 16396040913e25987d18806dad27b80082706025..514f64e1b52f4f4a65383800e6760f561fb85f02 100644 (file)
@@ -1096,7 +1096,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 
                case SIOCADDRT:
                case SIOCDELRT:
-                       if (!suser()) return -EPERM;
+                       if (!capable(CAP_NET_ADMIN)) return -EPERM;
                        return x25_route_ioctl(cmd, (void *)arg);
 
                case SIOCX25GSUBSCRIP: