summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-07-08 04:24:04 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-07-08 04:24:04 -0700
commit6fee4e4eae95a053b1148537c1fe1ee9ff3d7a45 (patch)
treefea61da3aecfaa64c024bea99e9216039d61fc5a
parent58af6e3af0578edece898ea59261812bad7a3576 (diff)
parenta1bafab5cbe2ce874fe5b0e012cc9ab74a672b39 (diff)
Resolve conflicts in ipconfig.c changes.
-rw-r--r--Documentation/eisa.txt60
-rw-r--r--Documentation/filesystems/Locking6
-rw-r--r--Documentation/pci.txt12
-rw-r--r--MAINTAINERS26
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/mm/numa.c4
-rw-r--r--arch/arm/mm/init.c4
-rw-r--r--arch/arm26/Config.help387
-rw-r--r--arch/arm26/Kconfig156
-rw-r--r--arch/arm26/config.in151
-rw-r--r--arch/arm26/kernel/Makefile2
-rw-r--r--arch/arm26/kernel/arch.c30
-rw-r--r--arch/arm26/kernel/asm-offsets.c2
-rw-r--r--arch/arm26/kernel/compat.c2
-rw-r--r--arch/arm26/kernel/dma.c2
-rw-r--r--arch/arm26/kernel/ecard.c20
-rw-r--r--arch/arm26/kernel/irq.c9
-rw-r--r--arch/arm26/kernel/process.c4
-rw-r--r--arch/arm26/kernel/setup.c73
-rw-r--r--arch/arm26/kernel/traps.c7
-rw-r--r--arch/arm26/lib/Makefile15
-rw-r--r--arch/arm26/machine/Makefile2
-rw-r--r--arch/arm26/machine/arch.c36
-rw-r--r--arch/arm26/machine/irq.c4
-rw-r--r--arch/arm26/mm/init.c6
-rw-r--r--arch/arm26/mm/mm-memc.c2
-rw-r--r--arch/cris/mm/tlb.c2
-rw-r--r--arch/i386/Kconfig8
-rw-r--r--arch/i386/kernel/cpu/common.c10
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c4
-rw-r--r--arch/i386/kernel/entry.S1
-rw-r--r--arch/i386/kernel/io_apic.c2
-rw-r--r--arch/i386/kernel/irq.c3
-rw-r--r--arch/i386/kernel/time.c29
-rw-r--r--arch/i386/kernel/timers/timer.c15
-rw-r--r--arch/i386/kernel/timers/timer_cyclone.c4
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c17
-rw-r--r--arch/i386/lib/delay.c2
-rw-r--r--arch/i386/mm/pageattr.c82
-rw-r--r--arch/i386/mm/pgtable.c2
-rw-r--r--arch/i386/pci/direct.c2
-rw-r--r--arch/i386/pci/irq.c16
-rw-r--r--arch/i386/pci/legacy.c26
-rw-r--r--arch/ia64/ia32/binfmt_elf32.c3
-rw-r--r--arch/ia64/kernel/sys_ia64.c1
-rw-r--r--arch/ia64/mm/init.c4
-rw-r--r--arch/m68knommu/Kconfig20
-rw-r--r--arch/m68knommu/platform/5282/config.c2
-rw-r--r--arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S7
-rw-r--r--arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S8
-rw-r--r--arch/m68knommu/platform/5307/MP3/crt0_ram.S8
-rw-r--r--arch/m68knommu/platform/5307/NETtel/crt0_ram.S8
-rw-r--r--arch/m68knommu/platform/68328/ints.c4
-rw-r--r--arch/m68knommu/platform/68360/config.c5
-rw-r--r--arch/m68knommu/platform/68VZ328/de2/config.c14
-rw-r--r--arch/m68knommu/vmlinux.lds.S4
-rw-r--r--arch/mips/kernel/sysirix.c5
-rw-r--r--arch/parisc/kernel/smp.c2
-rw-r--r--arch/ppc/Kconfig25
-rw-r--r--arch/ppc/boot/common/Makefile3
-rw-r--r--arch/ppc/boot/common/ns16550.c5
-rw-r--r--arch/ppc/boot/common/serial_stub.c28
-rw-r--r--arch/ppc/boot/simple/Makefile33
-rw-r--r--arch/ppc/boot/simple/direct.S15
-rw-r--r--arch/ppc/boot/simple/m8260_tty.c5
-rw-r--r--arch/ppc/boot/simple/m8xx_tty.c5
-rw-r--r--arch/ppc/configs/adir_defconfig2
-rw-r--r--arch/ppc/configs/apus_defconfig2
-rw-r--r--arch/ppc/configs/common_defconfig2
-rw-r--r--arch/ppc/configs/ev64260_defconfig2
-rw-r--r--arch/ppc/configs/gemini_defconfig2
-rw-r--r--arch/ppc/configs/ibmchrp_defconfig2
-rw-r--r--arch/ppc/configs/k2_defconfig2
-rw-r--r--arch/ppc/configs/lopec_defconfig2
-rw-r--r--arch/ppc/configs/mcpn765_defconfig2
-rw-r--r--arch/ppc/configs/menf1_defconfig1
-rw-r--r--arch/ppc/configs/mvme5100_defconfig2
-rw-r--r--arch/ppc/configs/pcore_defconfig2
-rw-r--r--arch/ppc/configs/pmac_defconfig2
-rw-r--r--arch/ppc/configs/power3_defconfig2
-rw-r--r--arch/ppc/configs/pplus_defconfig2
-rw-r--r--arch/ppc/configs/prpmc750_defconfig2
-rw-r--r--arch/ppc/configs/prpmc800_defconfig2
-rw-r--r--arch/ppc/configs/sandpoint_defconfig24
-rw-r--r--arch/ppc/configs/spruce_defconfig2
-rw-r--r--arch/ppc/configs/zx4500_defconfig560
-rw-r--r--arch/ppc/defconfig2
-rw-r--r--arch/ppc/kernel/ppc-stub.c10
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c2
-rw-r--r--arch/ppc/kernel/setup.c2
-rw-r--r--arch/ppc/platforms/Makefile3
-rw-r--r--arch/ppc/platforms/menf1.h24
-rw-r--r--arch/ppc/platforms/menf1_pci.c98
-rw-r--r--arch/ppc/platforms/menf1_setup.c283
-rw-r--r--arch/ppc/platforms/sandpoint.c719
-rw-r--r--arch/ppc/platforms/sandpoint.h56
-rw-r--r--arch/ppc/platforms/sandpoint_pci.c181
-rw-r--r--arch/ppc/platforms/sandpoint_serial.h49
-rw-r--r--arch/ppc/platforms/sandpoint_setup.c643
-rw-r--r--arch/ppc/platforms/zx4500.h68
-rw-r--r--arch/ppc/platforms/zx4500_pci.c138
-rw-r--r--arch/ppc/platforms/zx4500_serial.h46
-rw-r--r--arch/ppc/platforms/zx4500_setup.c359
-rw-r--r--arch/ppc/syslib/Makefile7
-rw-r--r--arch/ppc/syslib/gen550_dbg.c174
-rw-r--r--arch/ppc/syslib/gen550_kgdb.c84
-rw-r--r--arch/ppc/syslib/open_pic.c106
-rw-r--r--arch/ppc64/mm/init.c4
-rw-r--r--arch/ppc64/mm/numa.c16
-rw-r--r--arch/s390/kernel/compat_exec.c3
-rw-r--r--arch/s390/kernel/setup.c2
-rw-r--r--arch/sh/kernel/cpu/sh4/pci-sh7751.c2
-rw-r--r--arch/sparc64/Kconfig7
-rw-r--r--arch/sparc64/boot/Makefile6
-rw-r--r--arch/sparc64/kernel/irq.c4
-rw-r--r--arch/sparc64/kernel/process.c2
-rw-r--r--arch/sparc64/kernel/smp.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c13
-rw-r--r--arch/sparc64/kernel/traps.c5
-rw-r--r--arch/sparc64/lib/Makefile2
-rw-r--r--arch/sparc64/lib/xor.S356
-rw-r--r--arch/um/kernel/process_kern.c3
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c4
-rw-r--r--arch/x86_64/kernel/setup64.c2
-rw-r--r--arch/x86_64/mm/init.c2
-rw-r--r--arch/x86_64/mm/numa.c2
-rw-r--r--drivers/base/class.c20
-rw-r--r--drivers/base/firmware_class.c4
-rw-r--r--drivers/block/Makefile8
-rw-r--r--drivers/block/as-iosched.c1837
-rw-r--r--drivers/block/cciss.c5
-rw-r--r--drivers/block/elevator.c33
-rw-r--r--drivers/block/floppy.c2
-rw-r--r--drivers/block/genhd.c4
-rw-r--r--drivers/block/ll_rw_blk.c499
-rw-r--r--drivers/char/pcmcia/synclink_cs.c24
-rw-r--r--drivers/char/synclink.c21
-rw-r--r--drivers/char/synclinkmp.c25
-rw-r--r--drivers/eisa/eisa-bus.c234
-rw-r--r--drivers/eisa/eisa.ids6
-rw-r--r--drivers/eisa/pci_eisa.c3
-rw-r--r--drivers/eisa/virtual_root.c15
-rw-r--r--drivers/ide/ppc/pmac.c2
-rw-r--r--drivers/ieee1394/sbp2.c2
-rw-r--r--drivers/macintosh/macserial.c19
-rw-r--r--drivers/md/dm-ioctl.c4
-rw-r--r--drivers/md/dm.c5
-rw-r--r--drivers/message/i2o/i2o_scsi.c1
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/net/Kconfig2
-rw-r--r--drivers/net/e100/e100_main.c4
-rw-r--r--drivers/net/irda/irtty-sir.c30
-rw-r--r--drivers/net/irda/sir_dev.c22
-rw-r--r--drivers/net/irda/sir_kthread.c45
-rw-r--r--drivers/net/wan/comx.c4
-rw-r--r--drivers/net/wan/hdlc_generic.c7
-rw-r--r--drivers/parisc/eisa.c24
-rw-r--r--drivers/parisc/eisa_enumerator.c9
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c2
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c6
-rw-r--r--drivers/pci/pci-sysfs.c105
-rw-r--r--drivers/pci/pci.h1
-rw-r--r--drivers/pci/probe.c25
-rw-r--r--drivers/pci/search.c30
-rw-r--r--drivers/pnp/interface.c22
-rw-r--r--drivers/pnp/manager.c37
-rw-r--r--drivers/pnp/resource.c8
-rw-r--r--drivers/pnp/support.c24
-rw-r--r--drivers/scsi/scsi.c2
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/serial/68328serial.c1
-rw-r--r--drivers/serial/8250_cs.c2
-rw-r--r--drivers/serial/mcfserial.c1
-rw-r--r--fs/adfs/adfs.h2
-rw-r--r--fs/adfs/dir.c2
-rw-r--r--fs/affs/namei.c4
-rw-r--r--fs/afs/dir.c10
-rw-r--r--fs/afs/mntpt.c4
-rw-r--r--fs/aio.c2
-rw-r--r--fs/attr.c3
-rw-r--r--fs/autofs/root.c8
-rw-r--r--fs/autofs4/root.c14
-rw-r--r--fs/befs/linuxvfs.c4
-rw-r--r--fs/bfs/dir.c5
-rw-r--r--fs/binfmt_flat.c507
-rw-r--r--fs/block_dev.c10
-rw-r--r--fs/buffer.c15
-rw-r--r--fs/cifs/CHANGES10
-rw-r--r--fs/cifs/Makefile2
-rw-r--r--fs/cifs/README146
-rw-r--r--fs/cifs/TODO22
-rw-r--r--fs/cifs/cifs_unicode.c2
-rwxr-xr-xfs/cifs/cifsencrypt.c140
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsfs.h10
-rw-r--r--fs/cifs/cifsglob.h3
-rw-r--r--fs/cifs/cifspdu.h8
-rw-r--r--fs/cifs/cifsproto.h8
-rw-r--r--fs/cifs/cifssmb.c12
-rw-r--r--fs/cifs/connect.c23
-rw-r--r--fs/cifs/dir.c7
-rw-r--r--fs/cifs/inode.c6
-rw-r--r--fs/cifs/smbdes.c2
-rw-r--r--fs/cifs/smbencrypt.c121
-rw-r--r--fs/cifs/transport.c23
-rw-r--r--fs/cifs/xattr.c56
-rw-r--r--fs/coda/dir.c14
-rw-r--r--fs/coda/file.c11
-rw-r--r--fs/coda/pioctl.c6
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/devfs/base.c6
-rw-r--r--fs/dquot.c17
-rw-r--r--fs/efs/namei.c2
-rw-r--r--fs/eventpoll.c30
-rw-r--r--fs/exec.c57
-rw-r--r--fs/ext2/acl.c153
-rw-r--r--fs/ext2/acl.h3
-rw-r--r--fs/ext2/ext2.h10
-rw-r--r--fs/ext2/ialloc.c87
-rw-r--r--fs/ext2/namei.c4
-rw-r--r--fs/ext2/super.c3
-rw-r--r--fs/ext2/xattr.c240
-rw-r--r--fs/ext2/xattr_user.c16
-rw-r--r--fs/ext3/acl.c153
-rw-r--r--fs/ext3/acl.h3
-rw-r--r--fs/ext3/inode.c101
-rw-r--r--fs/ext3/namei.c5
-rw-r--r--fs/ext3/super.c3
-rw-r--r--fs/ext3/xattr.c281
-rw-r--r--fs/ext3/xattr_user.c16
-rw-r--r--fs/freevxfs/vxfs_lookup.c5
-rw-r--r--fs/fs-writeback.c2
-rw-r--r--fs/hfs/dir.c2
-rw-r--r--fs/hfs/dir_cap.c4
-rw-r--r--fs/hfs/dir_dbl.c10
-rw-r--r--fs/hfs/dir_nat.c4
-rw-r--r--fs/hfs/sysdep.c4
-rw-r--r--fs/hpfs/dir.c2
-rw-r--r--fs/hpfs/hpfs_fn.h4
-rw-r--r--fs/hpfs/namei.c4
-rw-r--r--fs/hugetlbfs/inode.c2
-rw-r--r--fs/intermezzo/dcache.c2
-rw-r--r--fs/intermezzo/dir.c17
-rw-r--r--fs/intermezzo/file.c2
-rw-r--r--fs/intermezzo/intermezzo_fs.h2
-rw-r--r--fs/intermezzo/vfs.c8
-rw-r--r--fs/isofs/namei.c2
-rw-r--r--fs/jbd/commit.c21
-rw-r--r--fs/jbd/transaction.c35
-rw-r--r--fs/jffs/inode-v23.c5
-rw-r--r--fs/jffs2/dir.c9
-rw-r--r--fs/jfs/acl.c2
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/namei.c6
-rw-r--r--fs/jfs/xattr.c26
-rw-r--r--fs/libfs.c2
-rw-r--r--fs/minix/namei.c5
-rw-r--r--fs/msdos/namei.c5
-rw-r--r--fs/namei.c93
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/dir.c17
-rw-r--r--fs/ncpfs/ioctl.c22
-rw-r--r--fs/nfs/dir.c73
-rw-r--r--fs/nfs/file.c5
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/vfs.c8
-rw-r--r--fs/ntfs/namei.c3
-rw-r--r--fs/open.c21
-rw-r--r--fs/openpromfs/inode.c9
-rw-r--r--fs/proc/base.c16
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/proc_misc.c9
-rw-r--r--fs/proc/root.c16
-rw-r--r--fs/qnx4/namei.c5
-rw-r--r--fs/ramfs/inode.c3
-rw-r--r--fs/reiserfs/namei.c5
-rw-r--r--fs/romfs/inode.c2
-rw-r--r--fs/smbfs/dir.c13
-rw-r--r--fs/smbfs/file.c2
-rw-r--r--fs/sysfs/bin.c25
-rw-r--r--fs/sysfs/dir.c22
-rw-r--r--fs/sysfs/file.c9
-rw-r--r--fs/sysv/namei.c4
-rw-r--r--fs/udf/file.c2
-rw-r--r--fs/udf/namei.c5
-rw-r--r--fs/ufs/namei.c5
-rw-r--r--fs/umsdos/dir.c4
-rw-r--r--fs/umsdos/emd.c2
-rw-r--r--fs/umsdos/namei.c4
-rw-r--r--fs/umsdos/rdir.c4
-rw-r--r--fs/vfat/namei.c9
-rw-r--r--fs/xattr.c4
-rw-r--r--fs/xfs/linux/xfs_iops.c43
-rw-r--r--fs/xfs/linux/xfs_super.c4
-rw-r--r--include/asm-alpha/div64.h15
-rw-r--r--include/asm-alpha/machvec.h2
-rw-r--r--include/asm-alpha/mmu_context.h15
-rw-r--r--include/asm-alpha/mmzone.h3
-rw-r--r--include/asm-arm/mmu_context.h4
-rw-r--r--include/asm-arm26/arch.h62
-rw-r--r--include/asm-arm26/bug.h11
-rw-r--r--include/asm-arm26/bugs.h2
-rw-r--r--include/asm-arm26/div64.h15
-rw-r--r--include/asm-arm26/ecard.h3
-rw-r--r--include/asm-arm26/mach-types.h1
-rw-r--r--include/asm-arm26/mmu_context.h4
-rw-r--r--include/asm-arm26/pgalloc.h4
-rw-r--r--include/asm-arm26/pgtable.h2
-rw-r--r--include/asm-arm26/statfs.h21
-rw-r--r--include/asm-arm26/thread_info.h2
-rw-r--r--include/asm-cris/div64.h17
-rw-r--r--include/asm-cris/mmu_context.h6
-rw-r--r--include/asm-generic/div64.h53
-rw-r--r--include/asm-h8300/div64.h14
-rw-r--r--include/asm-h8300/flat.h17
-rw-r--r--include/asm-h8300/mmu_context.h4
-rw-r--r--include/asm-i386/cacheflush.h5
-rw-r--r--include/asm-i386/hardirq.h2
-rw-r--r--include/asm-i386/mmu_context.h11
-rw-r--r--include/asm-i386/mmzone.h5
-rw-r--r--include/asm-i386/timer.h13
-rw-r--r--include/asm-i386/unistd.h3
-rw-r--r--include/asm-ia64/div64.h21
-rw-r--r--include/asm-ia64/mmu_context.h4
-rw-r--r--include/asm-m68k/div64.h9
-rw-r--r--include/asm-m68k/mmu_context.h6
-rw-r--r--include/asm-m68knommu/div64.h14
-rw-r--r--include/asm-m68knommu/flat.h8
-rw-r--r--include/asm-m68knommu/io.h9
-rw-r--r--include/asm-m68knommu/mmu_context.h4
-rw-r--r--include/asm-m68knommu/page.h2
-rw-r--r--include/asm-m68knommu/semaphore.h2
-rw-r--r--include/asm-m68knommu/uaccess.h21
-rw-r--r--include/asm-mips/mmu_context.h5
-rw-r--r--include/asm-mips64/div64.h19
-rw-r--r--include/asm-mips64/mmu_context.h2
-rw-r--r--include/asm-mips64/mmzone.h2
-rw-r--r--include/asm-parisc/div64.h55
-rw-r--r--include/asm-parisc/mmu_context.h6
-rw-r--r--include/asm-ppc/div64.h24
-rw-r--r--include/asm-ppc/mmu_context.h4
-rw-r--r--include/asm-ppc/serial.h4
-rw-r--r--include/asm-ppc64/div64.h19
-rw-r--r--include/asm-ppc64/mmu_context.h8
-rw-r--r--include/asm-ppc64/mmzone.h1
-rw-r--r--include/asm-s390/div64.h8
-rw-r--r--include/asm-s390/mmu_context.h8
-rw-r--r--include/asm-sh/div64.h21
-rw-r--r--include/asm-sh/mmu_context.h10
-rw-r--r--include/asm-sparc/div64.h12
-rw-r--r--include/asm-sparc/mmu_context.h8
-rw-r--r--include/asm-sparc64/div64.h15
-rw-r--r--include/asm-sparc64/hardirq.h8
-rw-r--r--include/asm-sparc64/mmu_context.h6
-rw-r--r--include/asm-sparc64/xor.h360
-rw-r--r--include/asm-um/mmu_context.h6
-rw-r--r--include/asm-v850/div64.h12
-rw-r--r--include/asm-v850/flat.h117
-rw-r--r--include/asm-v850/mmu_context.h4
-rw-r--r--include/asm-x86_64/div64.h15
-rw-r--r--include/asm-x86_64/mmu_context.h9
-rw-r--r--include/asm-x86_64/mmzone.h3
-rw-r--r--include/linux/acct.h2
-rw-r--r--include/linux/affs_fs.h4
-rw-r--r--include/linux/blkdev.h92
-rw-r--r--include/linux/buffer_head.h7
-rw-r--r--include/linux/coda_linux.h2
-rw-r--r--include/linux/compat_ioctl.h2
-rw-r--r--include/linux/dcache.h3
-rw-r--r--include/linux/device.h13
-rw-r--r--include/linux/efs_fs.h2
-rw-r--r--include/linux/eisa.h21
-rw-r--r--include/linux/elevator.h17
-rw-r--r--include/linux/eventpoll.h35
-rw-r--r--include/linux/ext3_fs.h6
-rw-r--r--include/linux/ext3_fs_i.h10
-rw-r--r--include/linux/flat.h20
-rw-r--r--include/linux/fs.h14
-rw-r--r--include/linux/hfs_fs.h2
-rw-r--r--include/linux/interrupt.h4
-rw-r--r--include/linux/ioport.h1
-rw-r--r--include/linux/irq_cpustat.h4
-rw-r--r--include/linux/iso_fs.h2
-rw-r--r--include/linux/kernel_stat.h3
-rw-r--r--include/linux/kobject.h2
-rw-r--r--include/linux/mm.h26
-rw-r--r--include/linux/mman.h3
-rw-r--r--include/linux/mmzone.h7
-rw-r--r--include/linux/msdos_fs.h8
-rw-r--r--include/linux/namei.h17
-rw-r--r--include/linux/netdevice.h8
-rw-r--r--include/linux/nfs_fs.h2
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/proc_fs.h4
-rw-r--r--include/linux/qnx4_fs.h5
-rw-r--r--include/linux/quota.h10
-rw-r--r--include/linux/sched.h5
-rw-r--r--include/linux/security.h16
-rw-r--r--include/linux/sem.h1
-rw-r--r--include/linux/slab.h4
-rw-r--r--include/linux/sysfs.h5
-rw-r--r--include/linux/umsdos_fs.p4
-rw-r--r--init/Kconfig3
-rw-r--r--ipc/sem.c95
-rw-r--r--kernel/acct.c26
-rw-r--r--kernel/exit.c17
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/ksyms.c3
-rw-r--r--kernel/sched.c25
-rw-r--r--kernel/signal.c61
-rw-r--r--kernel/softirq.c30
-rw-r--r--kernel/suspend.c8
-rw-r--r--kernel/sysctl.c4
-rw-r--r--kernel/timer.c16
-rw-r--r--kernel/user.c1
-rw-r--r--lib/Makefile2
-rw-r--r--lib/div64.c45
-rw-r--r--lib/kobject.c15
-rw-r--r--mm/bootmem.c6
-rw-r--r--mm/filemap.c62
-rw-r--r--mm/mmap.c71
-rw-r--r--mm/mprotect.c2
-rw-r--r--mm/mremap.c19
-rw-r--r--mm/nommu.c30
-rw-r--r--mm/page_alloc.c27
-rw-r--r--mm/readahead.c35
-rw-r--r--mm/shmem.c12
-rw-r--r--mm/slab.c226
-rw-r--r--mm/swap.c2
-rw-r--r--mm/swapfile.c6
-rw-r--r--net/bluetooth/hci_sock.c1
-rw-r--r--net/bluetooth/rfcomm/sock.c1
-rw-r--r--net/core/dev.c2
-rw-r--r--net/unix/af_unix.c2
-rw-r--r--security/capability.c65
-rw-r--r--security/dummy.c52
437 files changed, 8035 insertions, 6374 deletions
diff --git a/Documentation/eisa.txt b/Documentation/eisa.txt
index c27a2676dcea..8c8388da868a 100644
--- a/Documentation/eisa.txt
+++ b/Documentation/eisa.txt
@@ -46,12 +46,14 @@ root of an EISA bus. The eisa_root_device structure holds a reference
to this device, as well as some parameters for probing purposes.
struct eisa_root_device {
- struct list_head node;
- struct device *dev; /* Pointer to bridge device */
- struct resource *res;
- unsigned long bus_base_addr;
- int slots; /* Max slot number */
- int bus_nr; /* Set by eisa_root_register */
+ struct device *dev; /* Pointer to bridge device */
+ struct resource *res;
+ unsigned long bus_base_addr;
+ int slots; /* Max slot number */
+ int force_probe; /* Probe even when no slot 0 */
+ u64 dma_mask; /* from bridge device */
+ int bus_nr; /* Set by eisa_root_register */
+ struct resource eisa_root_res; /* ditto */
};
node : used for eisa_root_register internal purpose
@@ -59,6 +61,8 @@ dev : pointer to the root device
res : root device I/O resource
bus_base_addr : slot 0 address on this bus
slots : max slot number to probe
+force_probe : Probe even when slot 0 is empty (no EISA mainboard)
+dma_mask : Default DMA mask. Usualy the bridge device dma_mask.
bus_nr : unique bus id, set by eisa_root_register
** Driver :
@@ -87,7 +91,7 @@ driver : a generic driver, such as described in
Documentation/driver-model/driver.txt. Only .name,
.probe and .remove members are mandatory.
-An example is the 3c509 driver :
+An example is the 3c59x driver :
static struct eisa_device_id vortex_eisa_ids[] = {
{ "TCM5920", EISA_3C592_OFFSET },
@@ -116,15 +120,20 @@ encapsulated in a 'struct eisa_device' described as follows :
struct eisa_device {
struct eisa_device_id id;
int slot;
- unsigned long base_addr;
- struct resource res;
+ int state;
+ unsigned long base_addr;
+ struct resource res[EISA_MAX_RESOURCES];
+ u64 dma_mask;
struct device dev; /* generic device */
};
id : EISA id, as read from device. id.driver_data is set from the
matching driver EISA id.
slot : slot number which the device was detected on
-res : I/O resource allocated to this device
+state : set of flags indicating the state of the device. Current
+ flags are EISA_CONFIG_ENABLED and EISA_CONFIG_FORCED.
+res : set of four 256 bytes I/O regions allocated to this device
+dma_mask: DMA mask set from the parent device.
dev : generic device (see Documentation/driver-model/device.txt)
You can get the 'struct eisa_device' from 'struct device' using the
@@ -140,6 +149,32 @@ void *eisa_get_drvdata (struct eisa_device *edev):
Gets the pointer previously stored into the device's driver_data area.
+int eisa_get_region_index (void *addr);
+
+Returns the region number (0 <= x < EISA_MAX_RESOURCES) of a given
+address.
+
+** Kernel parameters :
+
+eisa_bus.enable_dev :
+
+A comma-separated list of slots to be enabled, even if the firmware
+set the card as disabled. The driver must be able to properly
+initialize the device in such conditions.
+
+eisa_bus.disable_dev :
+
+A comma-separated list of slots to be enabled, even if the firmware
+set the card as enabled. The driver won't be called to handle this
+device.
+
+virtual_root.force_probe :
+
+Force the probing code to probe EISA slots even when it cannot find an
+EISA compliant mainboard (nothing appears on slot 0). Defaultd to 0
+(don't force), and set to 1 (force probing) when either
+CONFIG_ALPHA_JENSEN or CONFIG_EISA_VLB_PRIMING are set.
+
** Random notes :
Converting an EISA driver to the new API mostly involves *deleting*
@@ -156,10 +191,13 @@ Unfortunately, most drivers are doing the probing by themselves, and
expect to have explored the whole machine when they exit their probe
routine.
+For example, switching your favorite EISA SCSI card to the "hotplug"
+model is "the right thing"(tm).
+
** Thanks :
I'd like to thank the following people for their help :
- Xavier Benigni for lending me a wonderful Alpha Jensen,
- James Bottomley, Jeff Garzik for getting this stuff into the kernel,
- Andries Brouwer for contributing numerous EISA ids,
-- Catrin Jones for coping with too many machines at home
+- Catrin Jones for coping with far too many machines at home.
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 03f43b68e801..969c8726f208 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -68,8 +68,8 @@ setattr: yes
permission: no
getattr: no
setxattr: yes
-getxattr: yes
-listxattr: yes
+getxattr: no
+listxattr: no
removexattr: yes
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_sem on
victim.
@@ -318,7 +318,7 @@ poll: no
ioctl: yes (see below)
mmap: no
open: maybe (see below)
-flush: yes
+flush: no
release: no
fsync: yes (see below)
fasync: yes (see below)
diff --git a/Documentation/pci.txt b/Documentation/pci.txt
index 15c52173d047..d30dc107ac62 100644
--- a/Documentation/pci.txt
+++ b/Documentation/pci.txt
@@ -7,14 +7,14 @@ The world of PCI is vast and it's full of (mostly unpleasant) surprises.
Different PCI devices have different requirements and different bugs --
because of this, the PCI support layer in Linux kernel is not as trivial
as one would wish. This short pamphlet tries to help all potential driver
-authors to find their way through the deep forests of PCI handling.
+authors find their way through the deep forests of PCI handling.
0. Structure of PCI drivers
~~~~~~~~~~~~~~~~~~~~~~~~~~~
There exist two kinds of PCI drivers: new-style ones (which leave most of
probing for devices to the PCI layer and support online insertion and removal
-of devices [thus supporting PCI, hot-pluggable PCI and CardBus in single
+of devices [thus supporting PCI, hot-pluggable PCI and CardBus in a single
driver]) and old-style ones which just do all the probing themselves. Unless
you have a very good reason to do so, please don't use the old way of probing
in any new code. After the driver finds the devices it wishes to operate
@@ -174,7 +174,7 @@ which enables the bus master bit in PCI_COMMAND register and also fixes
the latency timer value if it's set to something bogus by the BIOS.
If you want to use the PCI Memory-Write-Invalidate transaction,
-call pci_set_mwi(). This enables bit PCI_COMMAND bit for Mem-Wr-Inval
+call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval
and also ensures that the cache line size register is set correctly.
Make sure to check the return value of pci_set_mwi(), not all architectures
may support Memory-Write-Invalidate.
@@ -236,7 +236,7 @@ pci_clear_mwi() Disable Memory-Write-Invalidate transactions.
7. Miscellaneous hints
~~~~~~~~~~~~~~~~~~~~~~
When displaying PCI slot names to the user (for example when a driver wants
-to tell the user what card has it found), please use pci_dev->slot_name
+to tell the user what card has it found), please use pci_name(pci_dev)
for this purpose.
Always refer to the PCI devices by a pointer to the pci_dev structure.
@@ -248,6 +248,10 @@ can be pretty complex.
If you're going to use PCI bus mastering DMA, take a look at
Documentation/DMA-mapping.txt.
+Don't try to turn on Fast Back to Back writes in your driver. All devices
+on the bus need to be capable of doing it, so this is something which needs
+to be handled by platform and generic code, not individual drivers.
+
8. Obsolete functions
~~~~~~~~~~~~~~~~~~~~~
diff --git a/MAINTAINERS b/MAINTAINERS
index 73073266f7ad..9f2880a7c299 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -245,6 +245,21 @@ M: jschlst@samba.org
L: linux-atalk@lists.netspace.org
S: Maintained
+ARM26 ARCHITECTURE
+P: Ian Molton
+M: spyro@f2s.com
+S: Maintained
+
+ARM26/ARCHIMEDES
+P: Ian Molton
+M: spyro@f2s.com
+S: Maintained
+
+ARM26/A5000
+P: John Appleby
+M: john@dnsworld.co.uk
+S: Maintained
+
ARM MFM AND FLOPPY DRIVERS
P: Dave Gilbert
M: linux@treblig.org
@@ -1265,8 +1280,8 @@ L: linux-hams@vger.kernel.org
S: Maintained
NETWORK BLOCK DEVICE
-P: Pavel Machek
-M: pavel@atrey.karlin.mff.cuni.cz
+P: Paul Clements
+M: Paul.Clements@steeleye.com
S: Maintained
NETWORK DEVICE DRIVERS
@@ -2088,11 +2103,10 @@ L: user-mode-linux-user@lists.sourceforge.net
W: http://user-mode-linux.sourceforge.net
S: Maintained
-VFAT FILESYSTEM:
-P: Gordon Chaffee
-M: chaffee@cs.berkeley.edu
+FAT/VFAT/MSDOS FILESYSTEM:
+P: OGAWA Hirofumi
+M: hirofumi@mail.parknet.co.jp
L: linux-kernel@vger.kernel.org
-W: http://bmrc.berkeley.edu/people/chaffee
S: Maintained
VIA 82Cxxx AUDIO DRIVER
diff --git a/Makefile b/Makefile
index 4abb3ed46dff..51145c81be12 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 2
PATCHLEVEL = 5
-SUBLEVEL = 73
+SUBLEVEL = 74
EXTRAVERSION =
# *DOCUMENTATION*
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index 5a7ad83d367c..3100bb87bd50 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -338,7 +338,7 @@ void __init mem_init(void)
lmem_map = node_mem_map(nid);
pfn = NODE_DATA(nid)->node_start_pfn;
- for (i = 0; i < node_size(nid); i++, pfn++)
+ for (i = 0; i < node_spanned_pages(nid); i++, pfn++)
if (page_is_ram(pfn) && PageReserved(lmem_map+i))
reservedpages++;
}
@@ -372,7 +372,7 @@ show_mem(void)
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
for (nid = 0; nid < numnodes; nid++) {
struct page * lmem_map = node_mem_map(nid);
- i = node_size(nid);
+ i = node_spanned_pages(nid);
while (i-- > 0) {
total++;
if (PageReserved(lmem_map+i))
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 2fbcb7f5766a..90dcf272009c 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -79,7 +79,7 @@ void show_mem(void)
struct page *page, *end;
page = NODE_MEM_MAP(node);
- end = page + NODE_DATA(node)->node_size;
+ end = page + NODE_DATA(node)->node_spanned_pages;
do {
total++;
@@ -576,7 +576,7 @@ void __init mem_init(void)
for (node = 0; node < numnodes; node++) {
pg_data_t *pgdat = NODE_DATA(node);
- if (pgdat->node_size != 0)
+ if (pgdat->node_spanned_pages != 0)
totalram_pages += free_all_bootmem_node(pgdat);
}
diff --git a/arch/arm26/Config.help b/arch/arm26/Config.help
deleted file mode 100644
index a2a7f13d4eff..000000000000
--- a/arch/arm26/Config.help
+++ /dev/null
@@ -1,387 +0,0 @@
-CONFIG_ARM
- The ARM series is a line of low-power-consumption RISC chip designs
- licensed by ARM ltd and targeted at embedded applications.
-
-CONFIG_IDE
- If you say Y here, your kernel will be able to manage low cost mass
- storage units such as ATA/(E)IDE and ATAPI units. The most common
- cases are IDE hard drives and ATAPI CD-ROM drives.
-
- If your system is pure SCSI and doesn't use these interfaces, you
- can say N here.
-
- Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
- for mass storage units such as hard disks. It was designed by
- Western Digital and Compaq Computer in 1984. It was then named
- ST506. Quite a number of disks use the IDE interface.
-
- AT Attachment (ATA) is the superset of the IDE specifications.
- ST506 was also called ATA-1.
-
- Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is
- ATA-3. It provides support for larger disks (up to 8.4GB by means of
- the LBA standard), more disks (4 instead of 2) and for other mass
- storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is
- ATA-4 and provides faster (and more CPU friendly) transfer modes
- than previous PIO (Programmed processor Input/Output) from previous
- ATA/IDE standards by means of fast DMA controllers.
-
- ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
- CD-ROM drives, similar in many respects to the SCSI protocol.
-
- SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
- designed in order to prevent data corruption and disk crash by
- detecting pre hardware failure conditions (heat, access time, and
- the like...). Disks built since June 1995 may follow this standard.
- The kernel itself don't manage this; however there are quite a
- number of user programs such as smart that can query the status of
- SMART parameters disk.
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called ide.o.
-
- For further information, please read <file:Documentation/ide.txt>.
-
- If unsure, say Y.
-
-CONFIG_ISA
- Find out whether you have ISA slots on your motherboard. ISA is the
- name of a bus system, i.e. the way the CPU talks to the other stuff
- inside your box. Other bus systems are PCI, EISA, MicroChannel
- (MCA) or VESA. ISA is an older system, now being displaced by PCI;
- newer boards don't support it. If you have ISA, say Y, otherwise N.
-
-CONFIG_PREEMPT
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
-
-CONFIG_MCA
- MicroChannel Architecture is found in some IBM PS/2 machines and
- laptops. It is a bus system similar to PCI or ISA. See
- <file:Documentation/mca.txt> (and especially the web page given
- there) before attempting to build an MCA bus kernel.
-
-CONFIG_EISA
- The Extended Industry Standard Architecture (EISA) bus was
- developed as an open alternative to the IBM MicroChannel bus.
-
- The EISA bus provided some of the features of the IBM MicroChannel
- bus while maintaining backward compatibility with cards made for
- the older ISA bus. The EISA bus saw limited use between 1988 and
- 1995 when it was made obsolete by the PCI bus.
-
- Say Y here if you are building a kernel for an EISA-based machine.
-
- Otherwise, say N.
-
-CONFIG_HOTPLUG
- Say Y here if you want to plug devices into your computer while
- the system is running, and be able to use them quickly. In many
- cases, the devices can likewise be unplugged at any time too.
-
- One well known example of this is PCMCIA- or PC-cards, credit-card
- size devices such as network cards, modems or hard drives which are
- plugged into slots found on all modern laptop computers. Another
- example, used on modern desktops as well as laptops, is USB.
-
- Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
- software (at <http://linux-hotplug.sourceforge.net/>) and install it.
- Then your kernel will automatically call out to a user mode "policy
- agent" (/sbin/hotplug) to load modules and set up software needed
- to use devices as you hotplug them.
-
-CONFIG_KCORE_ELF
- If you enabled support for /proc file system then the file
- /proc/kcore will contain the kernel core image. This can be used
- in gdb:
-
- $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
-
- You have two choices here: ELF and A.OUT. Selecting ELF will make
- /proc/kcore appear in ELF core format as defined by the Executable
- and Linking Format specification. Selecting A.OUT will choose the
- old "a.out" format which may be necessary for some old versions
- of binutils or on some architectures.
-
- This is especially useful if you have compiled the kernel with the
- "-g" option to preserve debugging information. It is mainly used
- for examining kernel data structures on the live kernel so if you
- don't understand what this means or are not a kernel hacker, just
- leave it at its default value ELF.
-
-CONFIG_KCORE_AOUT
- Not necessary unless you're using a very out-of-date binutils
- version. You probably want KCORE_ELF.
-
-CONFIG_BINFMT_ELF
- ELF (Executable and Linkable Format) is a format for libraries and
- executables used across different architectures and operating
- systems. Saying Y here will enable your kernel to run ELF binaries
- and enlarge it by about 13 KB. ELF support under Linux has now all
- but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
- because it is portable (this does *not* mean that you will be able
- to run executables from different architectures or operating systems
- however) and makes building run-time libraries very easy. Many new
- executables are distributed solely in ELF format. You definitely
- want to say Y here.
-
- Information about ELF is contained in the ELF HOWTO available from
- <http://www.linuxdoc.org/docs.html#howto>.
-
- If you find that after upgrading from Linux kernel 1.2 and saying Y
- here, you still can't run any ELF binaries (they just crash), then
- you'll have to install the newest ELF runtime libraries, including
- ld.so (check the file <file:Documentation/Changes> for location and
- latest version).
-
- If you want to compile this as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called binfmt_elf.o. Saying M or N here is dangerous because
- some crucial programs on your system might be in ELF format.
-
-CONFIG_BINFMT_AOUT
- A.out (Assembler.OUTput) is a set of formats for libraries and
- executables used in the earliest versions of UNIX. Linux used the
- a.out formats QMAGIC and ZMAGIC until they were replaced with the
- ELF format.
-
- As more and more programs are converted to ELF, the use for a.out
- will gradually diminish. If you disable this option it will reduce
- your kernel by one page. This is not much and by itself does not
- warrant removing support. However its removal is a good idea if you
- wish to ensure that absolutely none of your programs will use this
- older executable format. If you don't know what to answer at this
- point then answer Y. If someone told you "You need a kernel with
- QMAGIC support" then you'll have to say Y here. You may answer M to
- compile a.out support as a module and later load the module when you
- want to use a program or library in a.out format. The module will be
- called binfmt_aout.o. Saying M or N here is dangerous though,
- because some crucial programs on your system might still be in A.OUT
- format.
-
-CONFIG_BINFMT_MISC
- If you say Y here, it will be possible to plug wrapper-driven binary
- formats into the kernel. You will like this especially when you use
- programs that need an interpreter to run like Java, Python or
- Emacs-Lisp. It's also useful if you often run DOS executables under
- the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>). Once you have
- registered such a binary class with the kernel, you can start one of
- those programs simply by typing in its name at a shell prompt; Linux
- will automatically feed it to the correct interpreter.
-
- You can do other nice things, too. Read the file
- <file:Documentation/binfmt_misc.txt> to learn how to use this
- feature, and <file:Documentation/java.txt> for information about how
- to include Java support.
-
- You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
- use this part of the kernel.
-
- You may say M here for module support and later load the module when
- you have use for it; the module is called binfmt_misc.o. If you
- don't know what to answer at this point, say Y.
-
-CONFIG_SCSI
- If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or
- any other SCSI device under Linux, say Y and make sure that you know
- the name of your SCSI host adapter (the card inside your computer
- that "speaks" the SCSI protocol, also called SCSI controller),
- because you will be asked for it.
-
- You also need to say Y here if you want support for the parallel
- port version of the 100 MB IOMEGA ZIP drive.
-
- This driver is also available as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want).
- The module will be called scsi_mod.o. If you want to compile it as
- a module, say M here and read <file:Documentation/modules.txt> and
- <file:Documentation/scsi.txt>. However, do not compile this as a
- module if your root file system (the one containing the directory /)
- is located on a SCSI device.
-
-CONFIG_NETDEVICES
- You can say N here if you don't intend to connect your Linux box to
- any other computer at all or if all your connections will be over a
- telephone line with a modem either via UUCP (UUCP is a protocol to
- forward mail and news between unix hosts over telephone lines; read
- the UUCP-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>) or dialing up a shell
- account or a BBS, even using term (term is a program which gives you
- almost full Internet connectivity if you have a regular dial up
- shell account on some Internet connected Unix computer. Read
- <http://www.bart.nl/~patrickr/term-howto/Term-HOWTO.html>).
-
- You'll have to say Y if your computer contains a network card that
- you want to use under Linux (make sure you know its name because you
- will be asked for it and read the Ethernet-HOWTO (especially if you
- plan to use more than one network card under Linux)) or if you want
- to use SLIP (Serial Line Internet Protocol is the protocol used to
- send Internet traffic over telephone lines or null modem cables) or
- CSLIP (compressed SLIP) or PPP (Point to Point Protocol, a better
- and newer replacement for SLIP) or PLIP (Parallel Line Internet
- Protocol is mainly used to create a mini network by connecting the
- parallel ports of two local machines) or AX.25/KISS (protocol for
- sending Internet traffic over amateur radio links).
-
- Make sure to read the NET-3-HOWTO. Eventually, you will have to read
- Olaf Kirch's excellent and free book "Network Administrator's
- Guide", to be found in <http://www.linuxdoc.org/docs.html#guide>. If
- unsure, say Y.
-
-CONFIG_MAGIC_SYSRQ
- If you say Y here, you will have some control over the system even
- if the system crashes for example during kernel debugging (e.g., you
- will be able to flush the buffer cache to disk, reboot the system
- immediately or dump some status information). This is accomplished
- by pressing various keys while holding SysRq (Alt+PrintScreen). It
- also works on a serial console (on PC hardware at least), if you
- send a BREAK and then within 5 seconds a command keypress. The
- keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
- unless you really know what this hack does.
-
-CONFIG_ARCH_ARCA5K
- This selects support for 'ARM26' CPUs (ARM 2 and 3)
-
-CONFIG_ARCH_A5K
- Say Y here to to support the Acorn A5000. Linux can support the
- internal IDE disk and CD-ROM interface, serial and parallel port,
- and the floppy drive. Note that on some A5000s the floppy is
- plugged into the wrong socket on the motherboard.
-
-CONFIG_ARCH_ARC
- The Acorn Archimedes was an personal computer based on an 8MHz ARM2
- processor, released in 1987. It supported 512K of RAM and 2 800K
- floppy disks. Picture and more detailed specifications at
- <http://www.computingmuseum.com/museum/archi.htm>.
-
-CONFIG_PAGESIZE_16
- Say Y here if your Archimedes or A5000 system has only 2MB of
- memory, otherwise say N. The resulting kernel will not run on a
- machine with 4MB of memory.
-
-CONFIG_FPE_NWFPE
- Say Y to include the NWFPE floating point emulator in the kernel.
- This is necessary to run most binaries. Linux does not currently
- support floating point hardware so you need to say Y here even if
- your machine has an FPA or floating point co-processor podule.
-
- It is also possible to say M to build the emulator as a module
- (nwfpe.o) or indeed to leave it out altogether. However, unless you
- know what you are doing this can easily render your machine
- unbootable. Saying Y is the safe option.
-
- You may say N here if you are going to load the Acorn FPEmulator
- early in the bootup.
-
-CONFIG_FPE_FASTFPE
- Say Y here to include the FAST floating point emulator in the kernel.
- This is an experimental much faster emulator which now also has full
- precision for the mantissa. It does not support any exceptions.
- It is very simple, and approximately 3-6 times faster than NWFPE.
-
- It should be sufficient for most programs. It may be not suitable
- for scientific calculations, but you have to check this for yourself.
- If you do not feel you need a faster FP emulation you should better
- choose NWFPE.
-
- It is also possible to say M to build the emulator as a module
- (fastfpe.o). But keep in mind that you should only load the FP
- emulator early in the bootup. You should never change from NWFPE to
- FASTFPE or vice versa in an active system!
-
-CONFIG_DEBUG_ERRORS
- This option controls verbose debugging information which can be
- printed when the kernel detects an internal error. This debugging
- information is useful to kernel hackers when tracking down problems,
- but mostly meaningless to other people. It's safe to say Y unless
- you are concerned with the code size or don't want to see these
- messages.
-
-CONFIG_NO_FRAME_POINTER
- If you say Y here, the resulting kernel will be slightly smaller and
- faster. However, when a problem occurs with the kernel, the
- information that is reported is severely limited. Most people
- should say N here.
-
-CONFIG_DEBUG_USER
- When a user program crashes due to an exception, the kernel can
- print a brief message explaining what the problem was. This is
- sometimes helpful for debugging but serves no purpose on a
- production system. Most people should say N here.
-
-CONFIG_DEBUG_INFO
- Say Y here to include source-level debugging information in the
- `vmlinux' binary image. This is handy if you want to use gdb or
- addr2line to debug the kernel. It has no impact on the in-memory
- footprint of the running kernel but it can increase the amount of
- time and disk space needed for compilation of the kernel. If in
- doubt say N.
-
-CONFIG_DEBUG_LL
- Say Y here to include definitions of printascii, printchar, printhex
- in the kernel. This is helpful if you are debugging code that
- executes before the console is initialized.
-
-CONFIG_NO_PGT_CACHE
- Normally the kernel maintains a `quicklist' of preallocated
- pagetable structures in order to increase performance. On machines
- with very few pages this may however be a loss. Say Y here to
- disable the pgtable cache.
-
-CONFIG_ARTHUR
- Say Y here to include the kernel code necessary if you want to run
- Acorn RISC OS/Arthur binaries under Linux. This code is still very
- experimental; if this sounds frightening, say N and sleep in peace.
- You can also say M here to compile this support as a module (which
- will be called arthur.o).
-
-CONFIG_CMDLINE
- On some architectures (EBSA110 and CATS), there is currently no way
- for the boot loader to pass arguments to the kernel. For these
- architectures, you should supply some command-line options at build
- time by entering them here. As a minimum, you should specify the
- memory size and the root device (e.g., mem=64M root=/dev/nfs).
-
-CONFIG_DEBUG_KERNEL
- Say Y here if you are developing drivers or trying to debug and
- identify kernel problems.
-
-CONFIG_DEBUG_SLAB
- Say Y here to have the kernel do limited verification on memory
- allocation as well as poisoning memory on free to catch use of freed
- memory.
-
-CONFIG_DEBUG_SPINLOCK
- Say Y here and build SMP to catch missing spinlock initialization
- and certain other kinds of spinlock errors commonly made. This is
- best used in conjunction with the NMI watchdog so that spinlock
- deadlocks are also debuggable.
-
-CONFIG_DEBUG_BUGVERBOSE
- Say Y here to make BUG() panics output the file name and line number
- of the BUG call as well as the EIP and oops trace. This aids
- debugging but costs about 70-100K of memory.
-
-CONFIG_ZBOOT_ROM
- Say Y here if you intend to execute your compressed kernel image (zImage)
- directly from ROM or flash. If unsure, say N.
-
-CONFIG_ZBOOT_ROM_TEXT
- The base address for zImage. Unless you have special requirements, you
- should not change this value.
-
-CONFIG_ZBOOT_ROM_BSS
- The base address of 64KiB of read/write memory, which must be available
- while the decompressor is running. Unless you have special requirements,
- you should not change this value.
-
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index b62382271dad..31d2e5de2c32 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -8,15 +8,8 @@ mainmenu "Linux Kernel Configuration"
config ARM
bool
default y
- help
- The ARM series is a line of low-power-consumption RISC chip designs
- licensed by ARM ltd and targeted at embedded applications and
- handhelds such as the Compaq IPAQ. ARM-based PCs are no longer
- manufactured, but legacy ARM-based PC hardware remains popular in
- Europe. There is an ARM Linux project with a web page at
- <http://www.arm.linux.org.uk/>.
-
-config ARCH_ARCA5K
+
+config ARM26
bool
default y
@@ -67,25 +60,25 @@ comment "Archimedes/A5000 Implementations (select only ONE)"
config ARCH_ARC
bool "Archimedes"
- depends on ARCH_ARCA5K
help
- The Acorn Archimedes was an personal computer based on an 8K ARM2
- processor, released in 1987. It supported 512K of RAM and 2 800K
- floppy disks. Picture and more detailed specifications at
- <http://www.computingmuseum.com/museum/archi.htm>.
+ Say Y to support the Acorn Archimedes.
+
+ The Acorn Archimedes was an personal computer based on an 8MHz ARM2
+ processor, released in 1987. It supported up to 16MB of RAM in
+ later models and floppy, harddisc, ethernet etc.
config ARCH_A5K
bool "A5000"
- depends on ARCH_ARCA5K
help
- Say Y here to to support the Acorn A5000. Linux can support the
+ Say Y here to to support the Acorn A5000.
+
+ Linux can support the
internal IDE disk and CD-ROM interface, serial and parallel port,
and the floppy drive. Note that on some A5000s the floppy is
plugged into the wrong socket on the motherboard.
config PAGESIZE_16
- bool "2MB physical memory"
- depends on ARCH_ARCA5K
+ bool "2MB physical memory (broken)"
help
Say Y here if your Archimedes or A5000 system has only 2MB of
memory, otherwise say N. The resulting kernel will not run on a
@@ -186,81 +179,7 @@ config KCORE_AOUT
endchoice
-config BINFMT_AOUT
- tristate "Kernel support for a.out binaries"
- ---help---
- A.out (Assembler.OUTput) is a set of formats for libraries and
- executables used in the earliest versions of UNIX. Linux used the
- a.out formats QMAGIC and ZMAGIC until they were replaced with the
- ELF format.
-
- As more and more programs are converted to ELF, the use for a.out
- will gradually diminish. If you disable this option it will reduce
- your kernel by one page. This is not much and by itself does not
- warrant removing support. However its removal is a good idea if you
- wish to ensure that absolutely none of your programs will use this
- older executable format. If you don't know what to answer at this
- point then answer Y. If someone told you "You need a kernel with
- QMAGIC support" then you'll have to say Y here. You may answer M to
- compile a.out support as a module and later load the module when you
- want to use a program or library in a.out format. The module will be
- called binfmt_aout. Saying M or N here is dangerous though,
- because some crucial programs on your system might still be in A.OUT
- format.
-
-config BINFMT_ELF
- tristate "Kernel support for ELF binaries"
- ---help---
- ELF (Executable and Linkable Format) is a format for libraries and
- executables used across different architectures and operating
- systems. Saying Y here will enable your kernel to run ELF binaries
- and enlarge it by about 13 KB. ELF support under Linux has now all
- but replaced the traditional Linux a.out formats (QMAGIC and ZMAGIC)
- because it is portable (this does *not* mean that you will be able
- to run executables from different architectures or operating systems
- however) and makes building run-time libraries very easy. Many new
- executables are distributed solely in ELF format. You definitely
- want to say Y here.
-
- Information about ELF is contained in the ELF HOWTO available from
- <http://www.linuxdoc.org/docs.html#howto>.
-
- If you find that after upgrading from Linux kernel 1.2 and saying Y
- here, you still can't run any ELF binaries (they just crash), then
- you'll have to install the newest ELF runtime libraries, including
- ld.so (check the file <file:Documentation/Changes> for location and
- latest version).
-
- If you want to compile this as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called binfmt_elf. Saying M or N here is dangerous because
- some crucial programs on your system might be in ELF format.
-
-config BINFMT_MISC
- tristate "Kernel support for MISC binaries"
- ---help---
- If you say Y here, it will be possible to plug wrapper-driven binary
- formats into the kernel. You will like this especially when you use
- programs that need an interpreter to run like Java, Python or
- Emacs-Lisp. It's also useful if you often run DOS executables under
- the Linux DOS emulator DOSEMU (read the DOSEMU-HOWTO, available from
- <http://www.linuxdoc.org/docs.html#howto>). Once you have
- registered such a binary class with the kernel, you can start one of
- those programs simply by typing in its name at a shell prompt; Linux
- will automatically feed it to the correct interpreter.
-
- You can do other nice things, too. Read the file
- <file:Documentation/binfmt_misc.txt> to learn how to use this
- feature, and <file:Documentation/java.txt> for information about how
- to include Java support.
-
- You must say Y to "/proc file system support" (CONFIG_PROC_FS) to
- use this part of the kernel.
-
- You may say M here for module support and later load the module when
- you have use for it; the module is called binfmt_misc. If you
- don't know what to answer at this point, say Y.
+source "fs/Kconfig.binfmt"
config PREEMPT
bool "Preemptible Kernel (EXPERIMENTAL)"
@@ -311,59 +230,8 @@ source "net/Kconfig"
source "net/irda/Kconfig"
-menu "ATA/ATAPI/MFM/RLL support"
-
-config IDE
- tristate "ATA/ATAPI/MFM/RLL support"
- ---help---
- If you say Y here, your kernel will be able to manage low cost mass
- storage units such as ATA/(E)IDE and ATAPI units. The most common
- cases are IDE hard drives and ATAPI CD-ROM drives.
-
- If your system is pure SCSI and doesn't use these interfaces, you
- can say N here.
-
- Integrated Disk Electronics (IDE aka ATA-1) is a connecting standard
- for mass storage units such as hard disks. It was designed by
- Western Digital and Compaq Computer in 1984. It was then named
- ST506. Quite a number of disks use the IDE interface.
-
- AT Attachment (ATA) is the superset of the IDE specifications.
- ST506 was also called ATA-1.
-
- Fast-IDE is ATA-2 (also named Fast ATA), Enhanced IDE (EIDE) is
- ATA-3. It provides support for larger disks (up to 8.4GB by means of
- the LBA standard), more disks (4 instead of 2) and for other mass
- storage units such as tapes and cdrom. UDMA/33 (aka UltraDMA/33) is
- ATA-4 and provides faster (and more CPU friendly) transfer modes
- than previous PIO (Programmed processor Input/Output) from previous
- ATA/IDE standards by means of fast DMA controllers.
-
- ATA Packet Interface (ATAPI) is a protocol used by EIDE tape and
- CD-ROM drives, similar in many respects to the SCSI protocol.
-
- SMART IDE (Self Monitoring, Analysis and Reporting Technology) was
- designed in order to prevent data corruption and disk crash by
- detecting pre hardware failure conditions (heat, access time, and
- the like...). Disks built since June 1995 may follow this standard.
- The kernel itself don't manage this; however there are quite a
- number of user programs such as smart that can query the status of
- SMART parameters disk.
-
- If you want to compile this driver as a module ( = code which can be
- inserted in and removed from the running kernel whenever you want),
- say M here and read <file:Documentation/modules.txt>. The module
- will be called ide.
-
- For further information, please read <file:Documentation/ide.txt>.
-
- If unsure, say Y.
-
source "drivers/ide/Kconfig"
-endmenu
-
-
source "drivers/scsi/Kconfig"
source "drivers/isdn/Kconfig"
diff --git a/arch/arm26/config.in b/arch/arm26/config.in
deleted file mode 100644
index 006a435d7591..000000000000
--- a/arch/arm26/config.in
+++ /dev/null
@@ -1,151 +0,0 @@
-#
-# For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
-#
-mainmenu_name "Linux Kernel Configuration"
-
-define_bool CONFIG_ARM y
-define_bool CONFIG_EISA n
-define_bool CONFIG_SBUS n
-define_bool CONFIG_MCA n
-define_bool CONFIG_UID16 y
-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
-define_bool CONFIG_GENERIC_BUST_SPINLOCK n
-define_bool CONFIG_GENERIC_ISA_DMA n
-
-source init/Config.in
-
-mainmenu_option next_comment
-comment 'System Type'
-
-define_bool CONFIG_ARCH_ARCA5K
-bool ' Archimedes' CONFIG_ARCH_ARC
-bool ' A5000' CONFIG_ARCH_A5K
-
-# Definitions to make life easier
-define_bool CONFIG_ARCH_ACORN y
-define_bool CONFIG_CPU_32 n
-define_bool CONFIG_CPU_26 y
-bool '2MB physical memory' CONFIG_PAGESIZE_16
-
-endmenu
-
-mainmenu_option next_comment
-comment 'General setup'
-
-define_bool CONFIG_FIQ y
-
-# Compressed boot loader in ROM. Yes, we really want to ask about
-# TEXT and BSS so we preserve their values in the config files.
-bool 'Compressed boot loader in ROM/flash' CONFIG_ZBOOT_ROM
-hex 'Compressed ROM boot loader base address' CONFIG_ZBOOT_ROM_TEXT 0
-hex 'Compressed ROM boot loader BSS address' CONFIG_ZBOOT_ROM_BSS 0
-
-comment 'At least one math emulation must be selected'
-define_bool CONFIG_FPE_NWFPE y
-choice 'Kernel core (/proc/kcore) format' \
- "ELF CONFIG_KCORE_ELF \
- A.OUT CONFIG_KCORE_AOUT" ELF
-tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
-tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
-string 'Default kernel command string' CONFIG_CMDLINE ""
-
-define_bool CONFIG_ALIGNMENT_TRAP n
-endmenu
-
-source drivers/parport/Config.in
-source drivers/pnp/Config.in
-source drivers/block/Config.in
-source drivers/md/Config.in
-source drivers/acorn/block/Config.in
-
-if [ "$CONFIG_NET" = "y" ]; then
- source net/Config.in
-
- mainmenu_option next_comment
- comment 'Network device support'
-
- bool 'Network device support' CONFIG_NETDEVICES
- if [ "$CONFIG_NETDEVICES" = "y" ]; then
- source drivers/net/Config.in
- fi
- endmenu
-fi
-
-mainmenu_option next_comment
-comment 'ATA/ATAPI/MFM/RLL support'
-
-tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
-
-if [ "$CONFIG_IDE" != "n" ]; then
- source drivers/ide/Config.in
-else
- define_bool CONFIG_BLK_DEV_HD n
-fi
-endmenu
-
-mainmenu_option next_comment
-comment 'SCSI support'
-
-tristate 'SCSI support' CONFIG_SCSI
-endmenu
-
-source drivers/isdn/Config.in
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source drivers/input/Config.in
-
-source drivers/char/Config.in
-if [ "$CONFIG_BUSMOUSE" = "y" ]; then
- define_bool CONFIG_KBDMOUSE y
-fi
-
-source drivers/media/Config.in
-
-source fs/Config.in
-
-if [ "$CONFIG_VT" = "y" ]; then
- mainmenu_option next_comment
- comment 'Console drivers'
- source drivers/video/Config.in
- endmenu
-fi
-
-mainmenu_option next_comment
-comment 'Sound'
-
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
- source sound/Config.in
-fi
-endmenu
-
-source drivers/misc/Config.in
-source drivers/usb/Config.in
-
-mainmenu_option next_comment
-comment 'Kernel hacking'
-
-# Always compile kernel with framepointer (until 2.4 real comes out)
-# Bug reports aren't much use without this.
-bool 'Compile kernel without frame pointer' CONFIG_NO_FRAME_POINTER
-bool 'Verbose user fault messages' CONFIG_DEBUG_USER
-bool 'Include debugging information in kernel binary' CONFIG_DEBUG_INFO
-
-bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
-dep_bool ' Debug memory allocations' CONFIG_DEBUG_SLAB $CONFIG_DEBUG_KERNEL
-dep_bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ $CONFIG_DEBUG_KERNEL
-dep_bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK $CONFIG_DEBUG_KERNEL
-dep_bool ' Wait queue debugging' CONFIG_DEBUG_WAITQ $CONFIG_DEBUG_KERNEL
-dep_bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE $CONFIG_DEBUG_KERNEL
-dep_bool ' Verbose kernel error messages' CONFIG_DEBUG_ERRORS $CONFIG_DEBUG_KERNEL
-# These options are only for real kernel hackers who want to get their hands dirty.
-dep_bool ' Kernel low-level debugging functions' CONFIG_DEBUG_LL $CONFIG_DEBUG_KERNEL
-endmenu
-
-source security/Config.in
-source lib/Config.in
diff --git a/arch/arm26/kernel/Makefile b/arch/arm26/kernel/Makefile
index 01b44b589dc8..59a75ea9a8dd 100644
--- a/arch/arm26/kernel/Makefile
+++ b/arch/arm26/kernel/Makefile
@@ -6,7 +6,7 @@ ENTRY_OBJ = entry.o
# Object file lists.
-obj-y := arch.o compat.o dma.o entry.o irq.o \
+obj-y := compat.o dma.o entry.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o ecard.o time-acorn.o dma.o \
ecard.o fiq.o time.o
diff --git a/arch/arm26/kernel/arch.c b/arch/arm26/kernel/arch.c
deleted file mode 100644
index 186de4fd6be3..000000000000
--- a/arch/arm26/kernel/arch.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * linux/arch/arm/kernel/arch.c
- *
- * Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/arch.h>
-#include <asm/page.h>
-
-unsigned int vram_size;
-
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
- memc_ctrl_reg = tag->u.acorn.memc_control_reg;
- number_mfm_drives = tag->u.acorn.adfsdrives;
- return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
diff --git a/arch/arm26/kernel/asm-offsets.c b/arch/arm26/kernel/asm-offsets.c
index 1e8764884737..b8d0442de9b5 100644
--- a/arch/arm26/kernel/asm-offsets.c
+++ b/arch/arm26/kernel/asm-offsets.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1995-2001 Russell King
* 2001-2002 Keith Owens
- * 2003-? Ian Molton
+ * 2003 Ian Molton
*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
diff --git a/arch/arm26/kernel/compat.c b/arch/arm26/kernel/compat.c
index 0f8644fe6a86..e3717ab1c043 100644
--- a/arch/arm26/kernel/compat.c
+++ b/arch/arm26/kernel/compat.c
@@ -26,7 +26,7 @@
#include <asm/mach-types.h>
#include <asm/page.h>
-#include <asm/arch.h>
+//#include <asm/arch.h>
//#include <asm/mach/irq.h>
/*
diff --git a/arch/arm26/kernel/dma.c b/arch/arm26/kernel/dma.c
index a6ae4e23651d..b4b8c7c4bbe8 100644
--- a/arch/arm26/kernel/dma.c
+++ b/arch/arm26/kernel/dma.c
@@ -2,7 +2,7 @@
* linux/arch/arm/kernel/dma.c
*
* Copyright (C) 1995-2000 Russell King
- * 2003-? Ian Molton
+ * 2003 Ian Molton
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index d69497a92811..b57a2e6b87eb 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -11,9 +11,8 @@
* Find all installed expansion cards, and handle interrupts from them.
*
* Created from information from Acorns RiscOS3 PRMs
- *
- * 08-Dec-1996 RMK Added code for the 9'th expansion card - the ether
- * podule slot.
+ * 15-Jun-2003 IM Modified from ARM32 (RiscPC capable) version
+ * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment.
* 06-May-1997 RMK Added blacklist for cards whose loader doesn't work.
* 12-Sep-1997 RMK Created new handling of interrupt enables/disables
* - cards can now register their own routine to control
@@ -21,10 +20,7 @@
* 29-Sep-1997 RMK Expansion card interrupt hardware not being re-enabled
* on reset from Linux. (Caused cards not to respond
* under RiscOS without hard reset).
- * 15-Feb-1998 RMK Added DMA support
- * 12-Sep-1998 RMK Added EASI support
- * 10-Jan-1999 RMK Run loaders in a simulated RISC OS environment.
- * 17-Apr-1999 RMK Support for EASI Type C cycles.
+ *
*/
#define ECARD_C
@@ -527,8 +523,7 @@ static int ecard_prints(char *buffer, ecard_t *ec)
{
char *start = buffer;
- buffer += sprintf(buffer, " %d: %s ", ec->slot_no,
- ec->type == ECARD_EASI ? "EASI" : " ");
+ buffer += sprintf(buffer, " %d: ", ec->slot_no);
if (ec->cid.id == 0) {
struct in_chunk_dir incd;
@@ -674,7 +669,7 @@ ecard_probe(int slot, card_type_t type)
memset(ec, 0, sizeof(ecard_t));
ec->slot_no = slot;
- ec->type = type;
+ ec->type = type;
ec->irq = NO_IRQ;
ec->fiq = NO_IRQ;
ec->dma = NO_DMA;
@@ -770,9 +765,8 @@ static int __init ecard_init(void)
printk("Probing expansion cards\n");
- for (slot = 0; slot < 8; slot ++) {
- if (ecard_probe(slot, ECARD_EASI) == -ENODEV)
- ecard_probe(slot, ECARD_IOC);
+ for (slot = 0; slot < 4; slot ++) {
+ ecard_probe(slot, ECARD_IOC);
}
irqhw = ecard_probeirqhw();
diff --git a/arch/arm26/kernel/irq.c b/arch/arm26/kernel/irq.c
index 3b4965a28193..ddd2ea591afd 100644
--- a/arch/arm26/kernel/irq.c
+++ b/arch/arm26/kernel/irq.c
@@ -41,7 +41,7 @@
* not be set too low to prevent false triggering. Conversely, if it
* is set too high, then you could miss a stuck IRQ.
*
- * Maybe we ought to set a timer and re-enable the IRQ at a later time?
+ * FIXME Maybe we ought to set a timer and re-enable the IRQ at a later time?
*/
#define MAX_IRQ_CNT 100000
@@ -49,7 +49,6 @@ static volatile unsigned long irq_err_count;
static spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
struct irqdesc irq_desc[NR_IRQS];
-void (*init_arch_irq)(void) __initdata = NULL;
/*
* Dummy mask/unmask handler
@@ -88,7 +87,6 @@ void disable_irq(unsigned int irq)
{
struct irqdesc *desc = irq_desc + irq;
unsigned long flags;
-
spin_lock_irqsave(&irq_controller_lock, flags);
if (!desc->depth++)
desc->enabled = 0;
@@ -114,7 +112,7 @@ void enable_irq(unsigned int irq)
spin_lock_irqsave(&irq_controller_lock, flags);
if (unlikely(!desc->depth)) {
printk("enable_irq(%u) unbalanced from %p\n", irq,
- __builtin_return_address(0));
+ __builtin_return_address(0)); //FIXME bum addresses reported - why?
} else if (!--desc->depth) {
desc->probing = 0;
desc->enabled = 1;
@@ -187,7 +185,6 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
unsigned int status;
spin_unlock(&irq_controller_lock);
-
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
@@ -700,6 +697,6 @@ void __init init_IRQ(void)
for (irq = 0, desc = irq_desc; irq < NR_IRQS; irq++, desc++)
*desc = bad_irq_desc;
- init_arch_irq();
+ arc_init_irq();
init_dma();
}
diff --git a/arch/arm26/kernel/process.c b/arch/arm26/kernel/process.c
index 6a4283a30199..bf8e0367be88 100644
--- a/arch/arm26/kernel/process.c
+++ b/arch/arm26/kernel/process.c
@@ -227,7 +227,9 @@ extern void free_page_8k(unsigned long page);
#define ll_alloc_task_struct() ((struct thread_info *)get_page_8k(GFP_KERNEL))
#define ll_free_task_struct(p) free_page_8k((unsigned long)(p))
-struct thread_info *alloc_thread_info(void)
+//FIXME - do we use *task param below looks like we dont, which is ok?
+//FIXME - if EXTRA_TASK_STRUCT is zero we can optimise the below away permanently. *IF* its supposed to be zero.
+struct thread_info *alloc_thread_info(struct task_struct *task)
{
struct thread_info *thread = NULL;
diff --git a/arch/arm26/kernel/setup.c b/arch/arm26/kernel/setup.c
index f4523c16ae0f..a5e07d757be7 100644
--- a/arch/arm26/kernel/setup.c
+++ b/arch/arm26/kernel/setup.c
@@ -30,7 +30,6 @@
#include <asm/mach-types.h>
#include <asm/tlbflush.h>
-#include <asm/arch.h>
#include <asm/irqchip.h>
#ifndef MEM_SIZE
@@ -66,6 +65,8 @@ unsigned int system_rev;
unsigned int system_serial_low;
unsigned int system_serial_high;
unsigned int elf_hwcap;
+unsigned int memc_ctrl_reg;
+unsigned int number_mfm_drives;
struct processor processor;
@@ -147,33 +148,6 @@ static void __init setup_processor(void)
cpu_proc_init();
}
-static struct machine_desc * __init setup_machine(unsigned int nr)
-{
- extern struct machine_desc __arch_info_begin, __arch_info_end;
- struct machine_desc *list;
-
- /*
- * locate architecture in the list of supported architectures.
- */
- for (list = &__arch_info_begin; list < &__arch_info_end; list++)
- if (list->nr == nr)
- break;
-
- /*
- * If the architecture type is not recognised, then we
- * can co nothing...
- */
- if (list >= &__arch_info_end) {
- printk("Architecture configuration botched (nr %d), unable "
- "to continue.\n", nr);
- while (1);
- }
-
- printk("Machine: %s\n", list->name);
-
- return list;
-}
-
/*
* Initial parsing of the command line. We need to pick out the
* memory size. We look for mem=size@start, where start and size
@@ -239,7 +213,7 @@ setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
}
static void __init
-request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
+request_standard_resources(struct meminfo *mi)
{
struct resource *res;
int i;
@@ -274,22 +248,18 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
request_resource(res, &kernel_data);
}
- if (mdesc->video_start) {
+/* FIXME - needed? if (mdesc->video_start) {
video_ram.start = mdesc->video_start;
video_ram.end = mdesc->video_end;
request_resource(&iomem_resource, &video_ram);
- }
+ }*/
/*
* Some machines don't have the possibility of ever
- * possessing lp0, lp1 or lp2
+ * possessing lp1 or lp2
*/
- if (mdesc->reserve_lp0)
+ if (0) /* FIXME - need to do this for A5k at least */
request_resource(&ioport_resource, &lp0);
- if (mdesc->reserve_lp1)
- request_resource(&ioport_resource, &lp1);
- if (mdesc->reserve_lp2)
- request_resource(&ioport_resource, &lp2);
}
/*
@@ -359,6 +329,15 @@ static int __init parse_tag_videotext(const struct tag *tag)
__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
#endif
+static int __init parse_tag_acorn(const struct tag *tag)
+{
+ memc_ctrl_reg = tag->u.acorn.memc_control_reg;
+ number_mfm_drives = tag->u.acorn.adfsdrives;
+ return 0;
+}
+
+__tagtable(ATAG_ACORN, parse_tag_acorn);
+
static int __init parse_tag_ramdisk(const struct tag *tag)
{
setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
@@ -467,15 +446,18 @@ static struct init_tags {
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
- struct machine_desc *mdesc;
char *from = default_command_line;
setup_processor();
- mdesc = setup_machine(machine_arch_type);
- machine_name = mdesc->name;
+ if(machine_arch_type == MACH_TYPE_A5K)
+ machine_name = "A5000";
+ else if(machine_arch_type == MACH_TYPE_ARCHIMEDES)
+ machine_name = "Archimedes";
+ else
+ machine_name = "UNKNOWN";
- if (mdesc->param_offset)
- tags = (struct tag *)mdesc->param_offset; //FIXME - ugly?
+ //FIXME - this may need altering when we get ROM images working
+ tags = (struct tag *)0x0207c000;
/*
* If we have the old style parameters, convert them to
@@ -501,12 +483,7 @@ void __init setup_arch(char **cmdline_p)
parse_cmdline(&meminfo, cmdline_p, from);
bootmem_init(&meminfo);
paging_init(&meminfo);
- request_standard_resources(&meminfo, mdesc);
-
- /*
- * Set up various architecture-specific pointers
- */
- init_arch_irq = mdesc->init_irq;
+ request_standard_resources(&meminfo);
#ifdef CONFIG_VT
#if defined(CONFIG_DUMMY_CONSOLE)
diff --git a/arch/arm26/kernel/traps.c b/arch/arm26/kernel/traps.c
index eaf86c9fedd1..d0e1bc6cf474 100644
--- a/arch/arm26/kernel/traps.c
+++ b/arch/arm26/kernel/traps.c
@@ -175,6 +175,11 @@ void show_trace_task(struct task_struct *tsk)
}
}
+/* FIXME - this is probably wrong.. */
+void show_stack(struct task_struct *task, unsigned long *sp) {
+ dump_mem("Stack: ", (unsigned long)sp, 8192+(unsigned long)task->thread_info);
+}
+
spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
/*
@@ -497,7 +502,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
die_if_kernel("unknown data abort code", regs, instr);
}
-void __bug(const char *file, int line, void *data)
+volatile void __bug(const char *file, int line, void *data)
{
printk(KERN_CRIT"kernel BUG at %s:%d!", file, line);
if (data)
diff --git a/arch/arm26/lib/Makefile b/arch/arm26/lib/Makefile
index d327dc7f385e..d05d6b0fd3e2 100644
--- a/arch/arm26/lib/Makefile
+++ b/arch/arm26/lib/Makefile
@@ -4,9 +4,7 @@
# Copyright (C) 1995-2000 Russell King
#
-L_TARGET := lib.a
-
-obj-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
+lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
copy_page.o delay.o findbit.o memchr.o memcpy.o \
memset.o memzero.o setbit.o \
@@ -16,15 +14,12 @@ obj-y := backtrace.o changebit.o csumipv6.o csumpartial.o \
ucmpdi2.o udivdi3.o lib1funcs.o ecard.o io-acorn.o \
floppydma.o io-readsb.o io-writesb.o io-writesl.o \
uaccess-kernel.o uaccess-user.o io-readsw-armv3.o \
- io-writesw-armv3.o io-readsl-armv3.o
-
-obj-m :=
-obj-n :=
-
-obj-$(CONFIG_VT)+= kbd.o
+ io-writesw-armv3.o io-readsl-armv3.o ecard.o \
+ io-acorn.o floppydma.o
-obj-y += ecard.o io-acorn.o floppydma.o
+lib-n :=
+lib-$(CONFIG_VT)+= kbd.o
csumpartialcopy.o: csumpartialcopygeneric.S
csumpartialcopyuser.o: csumpartialcopygeneric.S
diff --git a/arch/arm26/machine/Makefile b/arch/arm26/machine/Makefile
index f1211f9c9827..84642febab44 100644
--- a/arch/arm26/machine/Makefile
+++ b/arch/arm26/machine/Makefile
@@ -4,7 +4,7 @@
# Object file lists.
-obj-y := arch.o dma.o irq.o oldlatches.o \
+obj-y := dma.o irq.o oldlatches.o \
small_page.o
extra-y := head.o
diff --git a/arch/arm26/machine/arch.c b/arch/arm26/machine/arch.c
deleted file mode 100644
index 410c2852afaf..000000000000
--- a/arch/arm26/machine/arch.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * linux/arch/arm26/mach-arc/arch.c
- *
- * Copyright (C) 1998-2001 Russell King
- * Copyright (C) 2003 Ian Molton
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/tty.h>
-#include <linux/init.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-
-#include <asm/map.h>
-#include <asm/arch.h>
-
-extern void arc_init_irq(void);
-
-#ifdef CONFIG_ARCH_ARC
-MACHINE_START(ARCHIMEDES, "Acorn-Archimedes")
-#elif defined(CONFIG_ARCH_A5K)
-MACHINE_START(A5K, "Acorn-A5000")
-#endif
- MAINTAINER("Ian Molton")
- BOOT_PARAMS(0x0207c000)
- INITIRQ(arc_init_irq)
-MACHINE_END
-
diff --git a/arch/arm26/machine/irq.c b/arch/arm26/machine/irq.c
index 1c5f88fb2e52..158a7d29efbc 100644
--- a/arch/arm26/machine/irq.c
+++ b/arch/arm26/machine/irq.c
@@ -73,7 +73,6 @@ static struct irqchip arc_a_chip = {
static void arc_mask_irq_b(unsigned int irq)
{
unsigned int val, mask;
-
mask = 1 << (irq & 7);
val = ioc_readb(IOC_IRQMASKB);
ioc_writeb(val & ~mask, IOC_IRQMASKB);
@@ -94,7 +93,7 @@ static struct irqchip arc_b_chip = {
.unmask = arc_unmask_irq_b,
};
-/* FIXME - JMA none of these functions are used in arm26
+/* FIXME - JMA none of these functions are used in arm26 currently
static void arc_mask_irq_fiq(unsigned int irq)
{
unsigned int val, mask;
@@ -124,6 +123,7 @@ void __init arc_init_irq(void)
{
unsigned int irq, flags;
+ /* Disable all IOC interrupt sources */
ioc_writeb(0, IOC_IRQMASKA);
ioc_writeb(0, IOC_IRQMASKB);
ioc_writeb(0, IOC_FIQMASK);
diff --git a/arch/arm26/mm/init.c b/arch/arm26/mm/init.c
index c2105fb1a84c..989f08c19c62 100644
--- a/arch/arm26/mm/init.c
+++ b/arch/arm26/mm/init.c
@@ -32,7 +32,7 @@
#include <asm/setup.h>
#include <asm/tlb.h>
-#include <asm/arch.h>
+//#include <asm/arch.h>
#include <asm/map.h>
#define TABLE_SIZE PTRS_PER_PTE * sizeof(pte_t))
@@ -68,7 +68,7 @@ void show_mem(void)
page = NODE_MEM_MAP(0);
- end = page + NODE_DATA(0)->node_size;
+ end = page + NODE_DATA(0)->node_spanned_pages;
do {
total++;
@@ -353,7 +353,7 @@ void __init mem_init(void)
max_mapnr = virt_to_page(high_memory) - mem_map;
/* this will put all unused low memory onto the freelists */
- if (pgdat->node_size != 0)
+ if (pgdat->node_spanned_pages != 0)
totalram_pages += free_all_bootmem_node(pgdat);
printk(KERN_INFO "Memory:");
diff --git a/arch/arm26/mm/mm-memc.c b/arch/arm26/mm/mm-memc.c
index 15ec20e2750c..6b3d3ae806f4 100644
--- a/arch/arm26/mm/mm-memc.c
+++ b/arch/arm26/mm/mm-memc.c
@@ -70,11 +70,9 @@ void free_pgd_slow(pgd_t *pgd)
pgd_t *get_pgd_slow(struct mm_struct *mm)
{
- void *pg2k;
pgd_t *new_pgd, *init_pgd;
pmd_t *new_pmd, *init_pmd;
pte_t *new_pte, *init_pte;
- struct mm_struct bob;
new_pgd = alloc_pgd_table();
if (!new_pgd)
diff --git a/arch/cris/mm/tlb.c b/arch/cris/mm/tlb.c
index f5a97c9799fd..d31dc25b0070 100644
--- a/arch/cris/mm/tlb.c
+++ b/arch/cris/mm/tlb.c
@@ -283,7 +283,7 @@ get_mmu_context(struct mm_struct *mm)
void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, int cpu)
+ struct task_struct *tsk)
{
/* make sure we have a context */
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index ed5254e36eeb..3d78369616c0 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -1339,6 +1339,14 @@ config DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
+config DEBUG_PAGEALLOC
+ bool "Page alloc debugging"
+ depends on DEBUG_KERNEL
+ help
+ Unmap pages from the kernel linear mapping after free_pages().
+ This results in a large slowdown, but helps to find certain types
+ of memory corruptions.
+
config DEBUG_HIGHMEM
bool "Highmem debugging"
depends on DEBUG_KERNEL && HIGHMEM
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index a114c2ab7f83..99167880abbd 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -430,6 +430,14 @@ void __init early_cpu_init(void)
rise_init_cpu();
nexgen_init_cpu();
umc_init_cpu();
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ /* pse is not compatible with on-the-fly unmapping,
+ * disable it even if the cpus claim to support it.
+ */
+ clear_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability);
+ disable_pse = 1;
+#endif
}
/*
* cpu_init() initializes state that is per-CPU. Some data is already
@@ -487,7 +495,7 @@ void __init cpu_init (void)
current->active_mm = &init_mm;
if (current->mm)
BUG();
- enter_lazy_tlb(&init_mm, current, cpu);
+ enter_lazy_tlb(&init_mm, current);
load_esp0(t, thread->esp0);
set_tss_desc(cpu,t);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 91a8a25f635a..36181c7a0c64 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -268,8 +268,8 @@ static void change_speed (unsigned int index)
change_VID(vid);
} else {
/* Going up, so change VID first */
- change_VID(fid);
- change_FID(vid);
+ change_VID(vid);
+ change_FID(fid);
}
diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
index 5aef7a47a383..dafcae8663c8 100644
--- a/arch/i386/kernel/entry.S
+++ b/arch/i386/kernel/entry.S
@@ -876,5 +876,6 @@ ENTRY(sys_call_table)
.long sys_clock_nanosleep
.long sys_statfs64
.long sys_fstatfs64
+ .long sys_tgkill
nr_syscalls=(.-sys_call_table)/4
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 57159fe9face..3e5ec5c69f80 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -35,6 +35,7 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/desc.h>
+#include <asm/timer.h>
#include <mach_apic.h>
@@ -2052,7 +2053,6 @@ static inline void unlock_ExtINT_logic(void)
*/
static inline void check_timer(void)
{
- extern int timer_ack;
int pin1, pin2;
int vector;
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 6e0ff0a46b5c..314d47e8ec17 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -416,7 +416,6 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
* handled by some other CPU. (or is disabled)
*/
int irq = regs.orig_eax & 0xff; /* high bits used in ret_from_ code */
- int cpu = smp_processor_id();
irq_desc_t *desc = irq_desc + irq;
struct irqaction * action;
unsigned int status;
@@ -437,7 +436,7 @@ asmlinkage unsigned int do_IRQ(struct pt_regs regs)
}
}
#endif
- kstat_cpu(cpu).irqs[irq]++;
+ kstat_this_cpu.irqs[irq]++;
spin_lock(&desc->lock);
desc->handler->ack(irq);
/*
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index db98194645c3..9309c404e7a2 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -80,8 +80,7 @@ spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
spinlock_t i8253_lock = SPIN_LOCK_UNLOCKED;
EXPORT_SYMBOL(i8253_lock);
-extern struct timer_opts timer_none;
-struct timer_opts* timer = &timer_none;
+struct timer_opts *cur_timer = &timer_none;
/*
* This version of gettimeofday has microsecond resolution
@@ -93,14 +92,14 @@ void do_gettimeofday(struct timeval *tv)
unsigned long usec, sec;
do {
+ unsigned long lost;
+
seq = read_seqbegin(&xtime_lock);
- usec = timer->get_offset();
- {
- unsigned long lost = jiffies - wall_jiffies;
- if (lost)
- usec += lost * (1000000 / HZ);
- }
+ usec = cur_timer->get_offset();
+ lost = jiffies - wall_jiffies;
+ if (lost)
+ usec += lost * (1000000 / HZ);
sec = xtime.tv_sec;
usec += (xtime.tv_nsec / 1000);
} while (read_seqretry(&xtime_lock, seq));
@@ -126,7 +125,7 @@ int do_settimeofday(struct timespec *tv)
* wall time. Discover what correction gettimeofday() would have
* made, and then undo it!
*/
- tv->tv_nsec -= timer->get_offset() * NSEC_PER_USEC;
+ tv->tv_nsec -= cur_timer->get_offset() * NSEC_PER_USEC;
tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
while (tv->tv_nsec < 0) {
@@ -180,7 +179,7 @@ int timer_ack;
*/
unsigned long long monotonic_clock(void)
{
- return timer->monotonic_clock();
+ return cur_timer->monotonic_clock();
}
EXPORT_SYMBOL(monotonic_clock);
@@ -189,7 +188,8 @@ EXPORT_SYMBOL(monotonic_clock);
* timer_interrupt() needs to keep up the real-time clock,
* as well as call the "do_timer()" routine every clocktick
*/
-static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static inline void do_timer_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
{
#ifdef CONFIG_X86_IO_APIC
if (timer_ack) {
@@ -259,7 +259,7 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
write_seqlock(&xtime_lock);
- timer->mark_offset();
+ cur_timer->mark_offset();
do_timer_interrupt(irq, NULL, regs);
@@ -301,16 +301,13 @@ static int time_init_device(void)
device_initcall(time_init_device);
-
void __init time_init(void)
{
-
xtime.tv_sec = get_cmos_time();
wall_to_monotonic.tv_sec = -xtime.tv_sec;
xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
wall_to_monotonic.tv_nsec = -xtime.tv_nsec;
-
- timer = select_timer();
+ cur_timer = select_timer();
time_init_hook();
}
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
index 538c2c33f4e6..cf8f641d38f5 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -3,12 +3,6 @@
#include <linux/string.h>
#include <asm/timer.h>
-/* list of externed timers */
-extern struct timer_opts timer_pit;
-extern struct timer_opts timer_tsc;
-#ifdef CONFIG_X86_CYCLONE_TIMER
-extern struct timer_opts timer_cyclone;
-#endif
/* list of timers, ordered by preference, NULL terminated */
static struct timer_opts* timers[] = {
#ifdef CONFIG_X86_CYCLONE_TIMER
@@ -29,6 +23,15 @@ static int __init clock_setup(char* str)
}
__setup("clock=", clock_setup);
+
+/* The chosen timesource has been found to be bad.
+ * Fall back to a known good timesource (the PIT)
+ */
+void clock_fallback(void)
+{
+ cur_timer = &timer_pit;
+}
+
/* iterates through the list of timers, returning the first
* one that initializes successfully.
*/
diff --git a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c
index 0d2c2baf2a64..f88c490e0a21 100644
--- a/arch/i386/kernel/timers/timer_cyclone.c
+++ b/arch/i386/kernel/timers/timer_cyclone.c
@@ -11,6 +11,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <asm/timer.h>
#include <asm/io.h>
@@ -18,7 +19,6 @@
#include <asm/fixmap.h>
extern spinlock_t i8253_lock;
-extern unsigned long jiffies;
extern unsigned long calibrate_tsc(void);
/* Number of usecs that the last interrupt was delayed */
@@ -88,7 +88,7 @@ static void mark_offset_cyclone(void)
* between cyclone and pit reads (as noted when
* usec delta is > 90% # of usecs/tick)
*/
- if (abs(delay - delay_at_last_interrupt) > (900000/HZ))
+ if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
jiffies++;
}
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 02de71f68d9e..9988b67dd83a 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/cpufreq.h>
#include <linux/string.h>
+#include <linux/jiffies.h>
#include <asm/timer.h>
#include <asm/io.h>
@@ -21,7 +22,6 @@
int tsc_disable __initdata = 0;
extern spinlock_t i8253_lock;
-extern unsigned long jiffies;
static int use_tsc;
/* Number of usecs that the last interrupt was delayed */
@@ -124,6 +124,7 @@ static void mark_offset_tsc(void)
int countmp;
static int count1 = 0;
unsigned long long this_offset, last_offset;
+ static int lost_count = 0;
write_lock(&monotonic_lock);
last_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
@@ -178,9 +179,19 @@ static void mark_offset_tsc(void)
delta += delay_at_last_interrupt;
lost = delta/(1000000/HZ);
delay = delta%(1000000/HZ);
- if (lost >= 2)
+ if (lost >= 2) {
jiffies += lost-1;
+ /* sanity check to ensure we're not always loosing ticks */
+ if (lost_count++ > 100) {
+ printk(KERN_WARNING "Loosing too many ticks!\n");
+ printk(KERN_WARNING "TSC cannot be used as a timesource."
+ " (Are you running with SpeedStep?)\n");
+ printk(KERN_WARNING "Falling back to a sane timesource.\n");
+ clock_fallback();
+ }
+ } else
+ lost_count = 0;
/* update the monotonic base value */
this_offset = ((unsigned long long)last_tsc_high<<32)|last_tsc_low;
monotonic_base += cycles_2_ns(this_offset - last_offset);
@@ -194,7 +205,7 @@ static void mark_offset_tsc(void)
* between tsc and pit reads (as noted when
* usec delta is > 90% # of usecs/tick)
*/
- if (abs(delay - delay_at_last_interrupt) > (900000/HZ))
+ if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
jiffies++;
}
diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
index a678560d383f..028dd9bbd229 100644
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -25,7 +25,7 @@ extern struct timer_opts* timer;
void __delay(unsigned long loops)
{
- timer->delay(loops);
+ cur_timer->delay(loops);
}
inline void __const_udelay(unsigned long xloops)
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c
index 7bb9f7ebe469..51b777c42d53 100644
--- a/arch/i386/mm/pageattr.c
+++ b/arch/i386/mm/pageattr.c
@@ -13,6 +13,10 @@
#include <asm/processor.h>
#include <asm/tlbflush.h>
+static spinlock_t cpa_lock = SPIN_LOCK_UNLOCKED;
+static struct list_head df_list = LIST_HEAD_INIT(df_list);
+
+
static inline pte_t *lookup_address(unsigned long address)
{
pgd_t *pgd = pgd_offset_k(address);
@@ -31,10 +35,15 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot)
{
int i;
unsigned long addr;
- struct page *base = alloc_pages(GFP_KERNEL, 0);
+ struct page *base;
pte_t *pbase;
+
+ spin_unlock_irq(&cpa_lock);
+ base = alloc_pages(GFP_KERNEL, 0);
+ spin_lock_irq(&cpa_lock);
if (!base)
return NULL;
+
address = __pa(address);
addr = address & LARGE_PAGE_MASK;
pbase = (pte_t *)page_address(base);
@@ -87,7 +96,7 @@ static inline void revert_page(struct page *kpte_page, unsigned long address)
}
static int
-__change_page_attr(struct page *page, pgprot_t prot, struct page **oldpage)
+__change_page_attr(struct page *page, pgprot_t prot)
{
pte_t *kpte;
unsigned long address;
@@ -123,7 +132,7 @@ __change_page_attr(struct page *page, pgprot_t prot, struct page **oldpage)
}
if (cpu_has_pse && (atomic_read(&kpte_page->count) == 1)) {
- *oldpage = kpte_page;
+ list_add(&kpte_page->list, &df_list);
revert_page(kpte_page, address);
}
return 0;
@@ -134,12 +143,6 @@ static inline void flush_map(void)
on_each_cpu(flush_kernel_map, NULL, 1, 1);
}
-struct deferred_page {
- struct deferred_page *next;
- struct page *fpage;
-};
-static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
-
/*
* Change the page attributes of an page in the linear mapping.
*
@@ -156,47 +159,54 @@ static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */
int change_page_attr(struct page *page, int numpages, pgprot_t prot)
{
int err = 0;
- struct page *fpage;
int i;
+ unsigned long flags;
- down_write(&init_mm.mmap_sem);
+ spin_lock_irqsave(&cpa_lock, flags);
for (i = 0; i < numpages; i++, page++) {
- fpage = NULL;
- err = __change_page_attr(page, prot, &fpage);
+ err = __change_page_attr(page, prot);
if (err)
break;
- if (fpage) {
- struct deferred_page *df;
- df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL);
- if (!df) {
- flush_map();
- __free_page(fpage);
- } else {
- df->next = df_list;
- df->fpage = fpage;
- df_list = df;
- }
- }
}
- up_write(&init_mm.mmap_sem);
+ spin_unlock_irqrestore(&cpa_lock, flags);
return err;
}
void global_flush_tlb(void)
{
- struct deferred_page *df, *next_df;
+ LIST_HEAD(l);
+ struct list_head* n;
- down_read(&init_mm.mmap_sem);
- df = xchg(&df_list, NULL);
- up_read(&init_mm.mmap_sem);
+ BUG_ON(irqs_disabled());
+
+ spin_lock_irq(&cpa_lock);
+ list_splice_init(&df_list, &l);
+ spin_unlock_irq(&cpa_lock);
flush_map();
- for (; df; df = next_df) {
- next_df = df->next;
- if (df->fpage)
- __free_page(df->fpage);
- kfree(df);
- }
+ n = l.next;
+ while (n != &l) {
+ struct page *pg = list_entry(n, struct page, list);
+ n = n->next;
+ __free_page(pg);
+ }
}
+#ifdef CONFIG_DEBUG_PAGEALLOC
+void kernel_map_pages(struct page *page, int numpages, int enable)
+{
+ if (PageHighMem(page))
+ return;
+ /* the return value is ignored - the calls cannot fail,
+ * large pages are disabled at boot time.
+ */
+ change_page_attr(page, numpages, enable ? PAGE_KERNEL : __pgprot(0));
+ /* we should perform an IPI and flush all tlbs,
+ * but that can deadlock->flush only current cpu.
+ */
+ __flush_tlb_all();
+}
+EXPORT_SYMBOL(kernel_map_pages);
+#endif
+
EXPORT_SYMBOL(change_page_attr);
EXPORT_SYMBOL(global_flush_tlb);
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index 7ab983c90c53..941c2aa5236c 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -34,7 +34,7 @@ void show_mem(void)
show_free_areas();
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
- for (i = 0; i < pgdat->node_size; ++i) {
+ for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pgdat->node_mem_map + i;
total++;
if (PageHighMem(page))
diff --git a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
index 3a8be667ddfd..b99be74dc91b 100644
--- a/arch/i386/pci/direct.c
+++ b/arch/i386/pci/direct.c
@@ -177,7 +177,7 @@ static struct pci_raw_ops pci_direct_conf2 = {
* This should be close to trivial, but it isn't, because there are buggy
* chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
*/
-static int __devinit pci_sanity_check(struct pci_raw_ops *o)
+static int __init pci_sanity_check(struct pci_raw_ops *o)
{
u32 x = 0;
int devfn;
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index 53db10c42fea..4f9feba2fc95 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -102,13 +102,12 @@ static void __init pirq_peer_trick(void)
#endif
busmap[e->bus] = 1;
}
- for(i=1; i<256; i++)
- /*
- * It might be a secondary bus, but in this case its parent is already
- * known (ascending bus order) and therefore pci_scan_bus returns immediately.
- */
- if (busmap[i] && pci_scan_bus(i, &pci_root_ops, NULL))
+ for(i = 1; i < 256; i++) {
+ if (!busmap[i] || pci_find_bus(0, i))
+ continue;
+ if (pci_scan_bus(i, &pci_root_ops, NULL))
printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
+ }
pcibios_last_bus = -1;
}
@@ -196,15 +195,16 @@ static int pirq_piix_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
/*
* The VIA pirq rules are nibble-based, like ALI,
* but without the ugly irq number munging.
+ * However, PIRQD is in the upper instead of lower 4 bits.
*/
static int pirq_via_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
{
- return read_config_nybble(router, 0x55, pirq);
+ return read_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq);
}
static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
{
- write_config_nybble(router, 0x55, pirq, irq);
+ write_config_nybble(router, 0x55, pirq == 4 ? 5 : pirq, irq);
return 1;
}
diff --git a/arch/i386/pci/legacy.c b/arch/i386/pci/legacy.c
index 29fea7d6ad6c..c72bf1a59b7e 100644
--- a/arch/i386/pci/legacy.c
+++ b/arch/i386/pci/legacy.c
@@ -11,40 +11,26 @@
*/
static void __devinit pcibios_fixup_peer_bridges(void)
{
- int n;
- struct pci_bus *bus;
- struct pci_dev *dev;
- u16 l;
+ int n, devfn;
if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
return;
DBG("PCI: Peer bridge fixup\n");
- bus = kmalloc(sizeof(*bus), GFP_ATOMIC);
- dev = kmalloc(sizeof(*dev), GFP_ATOMIC);
- if (!bus || !dev) {
- printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__);
- goto exit;
- }
-
for (n=0; n <= pcibios_last_bus; n++) {
- if (pci_bus_exists(&pci_root_buses, n))
+ u32 l;
+ if (pci_find_bus(0, n))
continue;
- bus->number = n;
- bus->ops = &pci_root_ops;
- dev->bus = bus;
- for (dev->devfn=0; dev->devfn<256; dev->devfn += 8)
- if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
+ for (devfn = 0; devfn < 256; devfn += 8) {
+ if (!raw_pci_ops->read(0, n, devfn, PCI_VENDOR_ID, 2, &l) &&
l != 0x0000 && l != 0xffff) {
DBG("Found device at %02x:%02x [%04x]\n", n, dev->devfn, l);
printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
pci_scan_bus(n, &pci_root_ops, NULL);
break;
}
+ }
}
-exit:
- kfree(dev);
- kfree(bus);
}
static int __init pci_legacy_init(void)
diff --git a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
index dcc4982c2c66..8b2a41592746 100644
--- a/arch/ia64/ia32/binfmt_elf32.c
+++ b/arch/ia64/ia32/binfmt_elf32.c
@@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/mm.h>
+#include <linux/security.h>
#include <asm/param.h>
#include <asm/signal.h>
@@ -177,7 +178,7 @@ ia32_setup_arg_pages (struct linux_binprm *bprm)
if (!mpnt)
return -ENOMEM;
- if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+ if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
kmem_cache_free(vm_area_cachep, mpnt);
return -ENOMEM;
}
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 6de52294bd80..6d94e8b1a0ad 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -100,7 +100,6 @@ ia64_shmat (int shmid, void *shmaddr, int shmflg)
asmlinkage unsigned long
ia64_brk (unsigned long brk)
{
- extern int vm_enough_memory (long pages);
unsigned long rlim, retval, newbrk, oldbrk;
struct mm_struct *mm = current->mm;
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 8fc22262ce0f..4d37e437da3f 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -232,7 +232,7 @@ show_mem(void)
printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
printk("Node ID: %d\n", pgdat->node_id);
- for(i = 0; i < pgdat->node_size; i++) {
+ for(i = 0; i < pgdat->node_spanned_pages; i++) {
if (PageReserved(pgdat->node_mem_map+i))
reserved++;
else if (PageSwapCache(pgdat->node_mem_map+i))
@@ -240,7 +240,7 @@ show_mem(void)
else if (page_count(pgdat->node_mem_map + i))
shared += page_count(pgdat->node_mem_map + i) - 1;
}
- printk("\t%d pages of RAM\n", pgdat->node_size);
+ printk("\t%d pages of RAM\n", pgdat->node_spanned_pages);
printk("\t%d reserved pages\n", reserved);
printk("\t%d pages shared\n", shared);
printk("\t%d pages swap cached\n", cached);
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index 758525459878..2c08a7d8b27d 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -222,21 +222,17 @@ config UCDIMM
Support for the Arcturus Networks uDsimm module.
config DRAGEN2
- bool "Dragen Engine II board support"
+ bool "DragenEngine II board support"
depends on M68VZ328
help
- Support for the Dragen Engine II board.
+ Support for the DragenEngine II board.
-config HWADDR_FROMEEPROM
- bool " Read ETH address from EEPROM"
- depends on DRAGEN2
+config DIRECT_IO_ACCESS
+ bool " Allow user to access IO directly"
+ depends on (UCSIMM || UCDIMM || DRAGEN2)
help
- Use MAC address from EEPROM.
-
-config HWADDR_OFFSET
- int " Offset from start of EEPROM"
- default "2"
- depends on HWADDR_FROMEEPROM
+ Disable the CPU internal registers protection in user mode,
+ to allow a user application to read/write them.
config INIT_LCD
bool " Initialize LCD"
@@ -246,7 +242,7 @@ config INIT_LCD
config MEMORY_RESERVE
int " Memory reservation (MiB)"
- depends on (UCSIMM || UCDIMM || DRAGEN2)
+ depends on (UCSIMM || UCDIMM)
help
Reserve certain memory regions on 68x328 based boards.
diff --git a/arch/m68knommu/platform/5282/config.c b/arch/m68knommu/platform/5282/config.c
index 9548cf3a4268..c3fc68c8af66 100644
--- a/arch/m68knommu/platform/5282/config.c
+++ b/arch/m68knommu/platform/5282/config.c
@@ -62,7 +62,7 @@ void config_BSP(char *commandp, int size)
{
mcf_disableall();
-#if defined(CONFIG_BOOTPARAM)
+#ifdef CONFIG_BOOTPARAM
strncpy(commandp, CONFIG_BOOTPARAM_STRING, size);
commandp[size-1] = 0;
#else
diff --git a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S b/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
index a87ee519a60d..809b9ca2bdf0 100644
--- a/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
+++ b/arch/m68knommu/platform/5307/CLEOPATRA/crt0_ram.S
@@ -127,6 +127,7 @@ _start:
movc %d0,%CACR
+#ifdef CONFIG_ROMFS_FS
/*
* Move ROM filesystem above bss :-)
*/
@@ -148,6 +149,12 @@ _copy_romfs:
cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs
+#else /* CONFIG_ROMFS_FS */
+ lea.l _ebss, %a1
+ move.l %a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
/*
* Zero out the bss region.
*/
diff --git a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
index 070c0e8002d2..1fff8b293b77 100644
--- a/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
+++ b/arch/m68knommu/platform/5307/MOTOROLA/crt0_ram.S
@@ -110,6 +110,8 @@ _start:
movc %d0,%CACR
nop
+
+#ifdef CONFIG_ROMFS_FS
/*
* Move ROM filesystem above bss :-)
*/
@@ -131,6 +133,12 @@ _copy_romfs:
cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs
+#else /* CONFIG_ROMFS_FS */
+ lea.l _ebss, %a1
+ move.l %a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
/*
* Zero out the bss region.
*/
diff --git a/arch/m68knommu/platform/5307/MP3/crt0_ram.S b/arch/m68knommu/platform/5307/MP3/crt0_ram.S
index 822e1a49bac9..d99883ac3bd0 100644
--- a/arch/m68knommu/platform/5307/MP3/crt0_ram.S
+++ b/arch/m68knommu/platform/5307/MP3/crt0_ram.S
@@ -124,6 +124,8 @@ _start:
movec %d0,%CACR
nop
+
+#ifdef CONFIG_ROMFS_FS
/*
* Move ROM filesystem above bss :-)
*/
@@ -145,6 +147,12 @@ _copy_romfs:
cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs
+#else /* CONFIG_ROMFS_FS */
+ lea.l _ebss, %a1
+ move.l %a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
/*
* Zero out the bss region.
*/
diff --git a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S b/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
index 70eaf4cf7579..009a40506c06 100644
--- a/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
+++ b/arch/m68knommu/platform/5307/NETtel/crt0_ram.S
@@ -147,6 +147,8 @@ _start:
movec %d0,%CACR
nop
+
+#ifdef CONFIG_ROMFS_FS
/*
* Move ROM filesystem above bss :-)
*/
@@ -168,6 +170,12 @@ _copy_romfs:
cmp.l %a0, %a2 /* Check if at end */
bne _copy_romfs
+#else /* CONFIG_ROMFS_FS */
+ lea.l _ebss, %a1
+ move.l %a1, _ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
/*
* Zero out the bss region.
*/
diff --git a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c
index 2d864431dd42..290fdd07b7b0 100644
--- a/arch/m68knommu/platform/68328/ints.c
+++ b/arch/m68knommu/platform/68328/ints.c
@@ -81,6 +81,7 @@ unsigned int local_irq_count[NR_CPUS];
/* irq node variables for the 32 (potential) on chip sources */
static irq_node_t int_irq_list[NR_IRQS];
+#if !defined(CONFIG_DRAGEN2)
asm ("
.global _start, __ramend
.section .romvec
@@ -102,6 +103,7 @@ e_vectors:
ignore: rte
");
+#endif
/*
* This function should be called during kernel startup to initialize
@@ -204,7 +206,7 @@ int show_interrupts(struct seq_file *p, void *v)
seq_printf(p, " ");
seq_printf(p, "%s\n", int_irq_list[i].devname);
}
- seq_printf(p, " : %10u spurious", num_spurious);
+ seq_printf(p, " : %10u spurious\n", num_spurious);
return 0;
}
diff --git a/arch/m68knommu/platform/68360/config.c b/arch/m68knommu/platform/68360/config.c
index 6172044d0349..701303874109 100644
--- a/arch/m68knommu/platform/68360/config.c
+++ b/arch/m68knommu/platform/68360/config.c
@@ -205,9 +205,4 @@ void config_BSP(char *command, int len)
mach_hwclk = NULL;
mach_set_clock_mmss = NULL;
mach_reset = BSP_reset;
-
- //Kendrick's Change
- mach_trap_init = M68360_init_IRQ;
-
- config_M68360_irq();
}
diff --git a/arch/m68knommu/platform/68VZ328/de2/config.c b/arch/m68knommu/platform/68VZ328/de2/config.c
index bbba58b90de0..6673fe79aa14 100644
--- a/arch/m68knommu/platform/68VZ328/de2/config.c
+++ b/arch/m68knommu/platform/68VZ328/de2/config.c
@@ -36,7 +36,7 @@
#define TICKS_PER_JIFFY 41450
static void
-dragen2_sched_init(void (*timer_routine) (int, void *, struct pt_regs *))
+dragen2_sched_init(irqreturn_t (*timer_routine) (int, void *, struct pt_regs *))
{
/* disable timer 1 */
TCTL = 0;
@@ -183,14 +183,20 @@ static void init_hardware(void)
#endif
}
-void config_BSP(char *command, int len)
+void config_BSP(char *command, int size)
{
printk("68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
- command[0] = '\0'; /* no specific boot option */
+
+#if defined(CONFIG_BOOTPARAM)
+ strncpy(command, CONFIG_BOOTPARAM_STRING, size);
+ command[size-1] = 0;
+#else
+ memset(command, 0, size);
+#endif
init_hardware();
- mach_sched_init = dragen2_sched_init;
+ mach_sched_init = (void *)dragen2_sched_init;
mach_tick = dragen2_tick;
mach_gettimeoffset = dragen2_gettimeoffset;
mach_reset = dragen2_reset;
diff --git a/arch/m68knommu/vmlinux.lds.S b/arch/m68knommu/vmlinux.lds.S
index fa2004ada4ba..1ab8a31ef964 100644
--- a/arch/m68knommu/vmlinux.lds.S
+++ b/arch/m68knommu/vmlinux.lds.S
@@ -277,7 +277,9 @@ SECTIONS {
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
- SECURITY_INIT
+ __security_initcall_start = .;
+ *(.security_initcall.init)
+ __security_initcall_end = .;
. = ALIGN(4);
__initramfs_start = .;
*(.init.ramfs)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index 5722c28c1e9d..fdcc9d5bd057 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -28,6 +28,7 @@
#include <linux/vfs.h>
#include <linux/namei.h>
#include <linux/socket.h>
+#include <linux/security.h>
#include <asm/ptrace.h>
#include <asm/page.h>
@@ -527,8 +528,6 @@ asmlinkage int irix_gtime(struct pt_regs *regs)
return get_seconds();
}
-int vm_enough_memory(long pages);
-
/*
* IRIX is completely broken... it returns 0 on success, otherwise
* ENOMEM.
@@ -585,7 +584,7 @@ asmlinkage int irix_brk(unsigned long brk)
/*
* Check if we have enough memory..
*/
- if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+ if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
ret = -ENOMEM;
goto out;
}
diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c
index edf4e669ecfc..ce1094414dea 100644
--- a/arch/parisc/kernel/smp.c
+++ b/arch/parisc/kernel/smp.c
@@ -456,7 +456,7 @@ smp_cpu_init(int cpunum)
current->active_mm = &init_mm;
if(current->mm)
BUG();
- enter_lazy_tlb(&init_mm, current, cpunum);
+ enter_lazy_tlb(&init_mm, current);
init_IRQ(); /* make sure no IRQ's are enabled or pending */
}
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 9ade9f30eabb..66f1c0c6cb10 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -450,9 +450,6 @@ config EV64260
config SPRUCE
bool "IBM-Spruce"
-config MENF1
- bool "MEN-F1"
-
config LOPEC
bool "Motorola-LoPEC"
@@ -473,6 +470,10 @@ config PRPMC800
config SANDPOINT
bool "Motorola-Sandpoint"
+ help
+ Select SANDPOINT if configuring for a Motorola Sandpoint X3
+ or X3(b).
+ X3 (any flavor).
config ADIR
bool "SBS-Adirondack"
@@ -490,9 +491,6 @@ config GEMINI
series Single Board Computer. More information is available at:
<http://www.synergymicro.com/PressRel/97_10_15.html>.
-config ZX4500
- bool "Zynx-ZX4500"
-
endchoice
config PPC_CHRP
@@ -500,6 +498,11 @@ config PPC_CHRP
depends on PPC_MULTIPLATFORM
default y
+config PPC_GEN550
+ bool
+ depends on SANDPOINT
+ default y
+
config PPC_PMAC
bool
depends on PPC_MULTIPLATFORM
@@ -515,10 +518,6 @@ config PPC_OF
depends on PPC_PMAC || PPC_CHRP
default y
-config SANDPOINT_X3
- bool "Sandpoint X3"
- depends on SANDPOINT
-
config FORCE
bool
depends on 6xx && !8260 && (PCORE || POWERPMC250)
@@ -526,7 +525,7 @@ config FORCE
config EPIC_SERIAL_MODE
bool
- depends on 6xx && !8260 && (LOPEC || SANDPOINT_X3)
+ depends on 6xx && !8260 && (LOPEC || SANDPOINT)
default y
config WILLOW
@@ -536,7 +535,7 @@ config WILLOW
config MPC10X_STORE_GATHERING
bool "Enable MPC10x store gathering"
- depends on FORCE || MENF1 || SANDPOINT || ZX4500
+ depends on FORCE || SANDPOINT
config GT64260
bool
@@ -1528,7 +1527,7 @@ config BOOTX_TEXT
config SERIAL_TEXT_DEBUG
bool "Support for early boot texts over serial port"
- depends on 4xx || GT64260 || LOPEC || MCPN765 || PPLUS || PRPMC800 || SANDPOINT || ZX4500
+ depends on 4xx || GT64260 || LOPEC || MCPN765 || PPLUS || PRPMC800 || SANDPOINT
config OCP
bool
diff --git a/arch/ppc/boot/common/Makefile b/arch/ppc/boot/common/Makefile
index aefa82fcd7bc..6435b3722a13 100644
--- a/arch/ppc/boot/common/Makefile
+++ b/arch/ppc/boot/common/Makefile
@@ -8,7 +8,8 @@
# Tom Rini January 2001
#
-lib-y := string.o util.o misc-common.o
+lib-y := string.o util.o misc-common.o \
+ serial_stub.o
lib-$(CONFIG_PPC_PREP) += mpc10x_memory.o
lib-$(CONFIG_LOPEC) += mpc10x_memory.o
lib-$(CONFIG_PAL4) += cpc700_memory.o
diff --git a/arch/ppc/boot/common/ns16550.c b/arch/ppc/boot/common/ns16550.c
index 21cbfba89044..8c8db8d382d4 100644
--- a/arch/ppc/boot/common/ns16550.c
+++ b/arch/ppc/boot/common/ns16550.c
@@ -95,8 +95,3 @@ serial_tstc(unsigned long com_port)
{
return ((inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
}
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff --git a/arch/ppc/boot/common/serial_stub.c b/arch/ppc/boot/common/serial_stub.c
new file mode 100644
index 000000000000..2dc176ed0580
--- /dev/null
+++ b/arch/ppc/boot/common/serial_stub.c
@@ -0,0 +1,28 @@
+/*
+ * arch/ppc/boot/common/serial_stub.c
+ *
+ * This is a few stub routines to make the boot code cleaner looking when
+ * there is no serial port support doesn't need to be closed, for example.
+ *
+ * Author: Tom Rini <trini@mvista.com>
+ *
+ * 2003 (c) MontaVista, Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2. This program is licensed "as
+ * is" without any warranty of any kind, whether express or implied.
+ */
+
+void __attribute__ ((weak))
+serial_fixups(void)
+{
+}
+
+unsigned long __attribute__ ((weak))
+serial_init(int chan, void *ignored)
+{
+ return 0;
+}
+
+void __attribute__ ((weak))
+serial_close(unsigned long com_port)
+{
+}
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index 94217ae45849..3c45f8bda059 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -47,28 +47,20 @@ endif
ifeq ($(CONFIG_EBONY),y)
ZIMAGE := zImage-TREE
ZIMAGEINITRD := zImage.initrd-TREE
-EXTRA := direct.o
END := ebony
ENTRYPOINT := 0x01000000
TFTPIMAGE := /tftpboot/zImage.$(END)
endif
ifeq ($(CONFIG_EV64260),y)
-EXTRA := direct.o misc-ev64260.o
+EXTRA := misc-ev64260.o
TFTPIMAGE := /tftpboot/zImage.ev64260
endif
ifeq ($(CONFIG_GEMINI),y)
ZIMAGE := zImage-STRIPELF
ZIMAGEINITRD := zImage.initrd-STRIPELF
-EXTRA := direct.o
END := gemini
TFTPIMAGE := /tftpboot/zImage.$(END)
endif
-ifeq ($(CONFIG_MENF1),y)
-ZIMAGE := zImage-MENF1
-ZIMAGEINITRD := zImage.initrd-MENF1
-EXTRA := chrpmap.o
-TFTPIMAGE := /tftpboot/zImage.menf1
-endif
ifeq ($(CONFIG_K2),y)
EXTRA := legacy.o
TFTPIMAGE := /tftpboot/zImage.k2
@@ -78,7 +70,6 @@ endif
ifeq ($(CONFIG_MCPN765)$(CONFIG_MVME5100)$(CONFIG_PRPMC750)$(CONFIG_PRPMC800)$(CONFIG_LOPEC)$(CONFIG_PPLUS),y)
ZIMAGE := zImage-PPLUS
ZIMAGEINITRD := zImage.initrd-PPLUS
-EXTRA := direct.o
TFTPIMAGE := /tftpboot/zImage.pplus
ZNETBOOT := zImage.pplus
ZNETBOOTRD := zImage.initrd.pplus
@@ -86,9 +77,6 @@ endif
ifeq ($(CONFIG_PPLUS),y)
EXTRA := legacy.o
endif
-ifeq ($(CONFIG_PAL4),y)
-EXTRA := direct.o
-endif
ifeq ($(CONFIG_PCORE)$(CONFIG_POWERPMC250),y)
ZIMAGE := zImage-STRIPELF
ZIMAGEINITRD := zImage.initrd-STRIPELF
@@ -96,30 +84,17 @@ EXTRA := chrpmap.o
END := pcore
TFTPIMAGE := /tftpboot/zImage.$(END)
endif
-# The PowerPMC 250 needs the dummy serial_fixups()
-ifeq ($(CONFIG_POWERPMC250),y)
-EXTRA := direct.o
-endif
ifeq ($(CONFIG_SANDPOINT),y)
-EXTRA := direct.o
TFTPIMAGE := /tftpboot/zImage.sandpoint
endif
ifeq ($(CONFIG_SPRUCE),y)
ZIMAGE := zImage-TREE
ZIMAGEINITRD := zImage.initrd-TREE
-EXTRA := direct.o
END := spruce
ENTRYPOINT := 0x00800000
MISC := misc-spruce.o
TFTPIMAGE := /tftpboot/zImage.$(END)
endif
-ifeq ($(CONFIG_ZX4500),y)
-ZIMAGE := zImage-STRIPELF
-ZIMAGEINITRD := zImage.initrd-STRIPELF
-EXTRA := direct.o
-END := zx4500
-TFTPIMAGE := /tftpboot/zImage.$(END)
-endif
ifeq ($(CONFIG_SMP),y)
TFTPIMAGE += .smp
endif
@@ -221,12 +196,6 @@ $(images)/zImage.initrd-TREE: $(obj)/zvmlinux.initrd $(MKTREE)
$(MKTREE) $(obj)/zvmlinux.initrd $(images)/zImage.initrd.$(END) \
$(ENTRYPOINT)
-$(images)/zImage-MENF1: $(obj)/zvmlinux $(MKPREP)
- $(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.menf1
-
-$(images)/zImage.initrd-MENF1: $(obj)/zvmlinux.initrd $(MKPREP)
- $(MKPREP) -pbp $(obj)/zvmlinux.initrd $(images)/zImage.initrd.menf1
-
$(images)/zImage-PPLUS: $(obj)/zvmlinux $(MKPREP) $(MKBUGBOOT)
$(MKPREP) -pbp $(obj)/zvmlinux $(images)/zImage.pplus
$(MKBUGBOOT) $(obj)/zvmlinux $(images)/zImage.bugboot
diff --git a/arch/ppc/boot/simple/direct.S b/arch/ppc/boot/simple/direct.S
deleted file mode 100644
index b5ced833e370..000000000000
--- a/arch/ppc/boot/simple/direct.S
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * arch/ppc/boot/simple/direct.S
- *
- * Author: Tom Rini <trini@mvista.com>
- *
- * This is an empty function for machines which use SERIAL_IO_MEM
- * and don't need ISA_io set to anything but 0, or perform any other
- * serial fixups.
- */
-
- .text
-
- .globl serial_fixups
-serial_fixups:
- blr
diff --git a/arch/ppc/boot/simple/m8260_tty.c b/arch/ppc/boot/simple/m8260_tty.c
index 120df32fe9cf..9d1d54a5e8f2 100644
--- a/arch/ppc/boot/simple/m8260_tty.c
+++ b/arch/ppc/boot/simple/m8260_tty.c
@@ -311,8 +311,3 @@ serial_tstc(void *ignored)
return(!(rbdf->cbd_sc & BD_SC_EMPTY));
}
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff --git a/arch/ppc/boot/simple/m8xx_tty.c b/arch/ppc/boot/simple/m8xx_tty.c
index 93b59a3bc1c7..1d2778e248c6 100644
--- a/arch/ppc/boot/simple/m8xx_tty.c
+++ b/arch/ppc/boot/simple/m8xx_tty.c
@@ -288,8 +288,3 @@ serial_tstc(void *ignored)
return(!(rbdf->cbd_sc & BD_SC_EMPTY));
}
-
-void
-serial_close(unsigned long com_port)
-{
-}
diff --git a/arch/ppc/configs/adir_defconfig b/arch/ppc/configs/adir_defconfig
index aef58609eb8a..90ddd552a9dc 100644
--- a/arch/ppc/configs/adir_defconfig
+++ b/arch/ppc/configs/adir_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_ADIR=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_ALTIVEC is not set
diff --git a/arch/ppc/configs/apus_defconfig b/arch/ppc/configs/apus_defconfig
index 2ccbd93d1e85..718364870856 100644
--- a/arch/ppc/configs/apus_defconfig
+++ b/arch/ppc/configs/apus_defconfig
@@ -56,7 +56,6 @@ CONFIG_APUS=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@ CONFIG_APUS=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_ALTIVEC is not set
diff --git a/arch/ppc/configs/common_defconfig b/arch/ppc/configs/common_defconfig
index 5e50731b4db1..23d13c9aa6ef 100644
--- a/arch/ppc/configs/common_defconfig
+++ b/arch/ppc/configs/common_defconfig
@@ -56,7 +56,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
diff --git a/arch/ppc/configs/ev64260_defconfig b/arch/ppc/configs/ev64260_defconfig
index d6204290b3ad..c5bfc64d7831 100644
--- a/arch/ppc/configs/ev64260_defconfig
+++ b/arch/ppc/configs/ev64260_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
CONFIG_EV64260=y
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_EV64260=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_GT64260=y
CONFIG_SERIAL_CONSOLE_BAUD=115200
# CONFIG_SMP is not set
diff --git a/arch/ppc/configs/gemini_defconfig b/arch/ppc/configs/gemini_defconfig
index 98d499db74c3..324f8a7ae156 100644
--- a/arch/ppc/configs/gemini_defconfig
+++ b/arch/ppc/configs/gemini_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
CONFIG_GEMINI=y
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
CONFIG_ALTIVEC=y
diff --git a/arch/ppc/configs/ibmchrp_defconfig b/arch/ppc/configs/ibmchrp_defconfig
index 66017e5bbfeb..ef4bd5c260de 100644
--- a/arch/ppc/configs/ibmchrp_defconfig
+++ b/arch/ppc/configs/ibmchrp_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
diff --git a/arch/ppc/configs/k2_defconfig b/arch/ppc/configs/k2_defconfig
index c345891ae749..a7bca0e729e9 100644
--- a/arch/ppc/configs/k2_defconfig
+++ b/arch/ppc/configs/k2_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PPC_STD_MMU=y
CONFIG_K2=y
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_CPC710_DATA_GATHERING is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ppc/configs/lopec_defconfig b/arch/ppc/configs/lopec_defconfig
index 70962e27db3d..f4d189fc3fe0 100644
--- a/arch/ppc/configs/lopec_defconfig
+++ b/arch/ppc/configs/lopec_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
CONFIG_LOPEC=y
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_LOPEC=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_EPIC_SERIAL_MODE=y
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ppc/configs/mcpn765_defconfig b/arch/ppc/configs/mcpn765_defconfig
index 851a94f7ed54..23b969014ad2 100644
--- a/arch/ppc/configs/mcpn765_defconfig
+++ b/arch/ppc/configs/mcpn765_defconfig
@@ -50,7 +50,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
CONFIG_MCPN765=y
# CONFIG_MVME5100 is not set
@@ -62,7 +61,6 @@ CONFIG_MCPN765=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
CONFIG_ALTIVEC=y
diff --git a/arch/ppc/configs/menf1_defconfig b/arch/ppc/configs/menf1_defconfig
index b9d61c21ff37..64eece52ad33 100644
--- a/arch/ppc/configs/menf1_defconfig
+++ b/arch/ppc/configs/menf1_defconfig
@@ -67,7 +67,6 @@ CONFIG_MENF1=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_MPC10X_STORE_GATHERING=y
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ppc/configs/mvme5100_defconfig b/arch/ppc/configs/mvme5100_defconfig
index 69e9c155f484..67a31c66cea5 100644
--- a/arch/ppc/configs/mvme5100_defconfig
+++ b/arch/ppc/configs/mvme5100_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
CONFIG_MVME5100=y
@@ -67,7 +66,6 @@ CONFIG_MVME5100=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_MVME5100_IPMC761_PRESENT is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ppc/configs/pcore_defconfig b/arch/ppc/configs/pcore_defconfig
index b5568f2c374a..13db3dcada77 100644
--- a/arch/ppc/configs/pcore_defconfig
+++ b/arch/ppc/configs/pcore_defconfig
@@ -55,7 +55,6 @@ CONFIG_PCORE=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PCORE=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_FORCE=y
# CONFIG_MPC10X_STORE_GATHERING is not set
# CONFIG_SMP is not set
diff --git a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
index 411322433e7f..86cddf4e9b52 100644
--- a/arch/ppc/configs/pmac_defconfig
+++ b/arch/ppc/configs/pmac_defconfig
@@ -57,7 +57,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -69,7 +68,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
diff --git a/arch/ppc/configs/power3_defconfig b/arch/ppc/configs/power3_defconfig
index a986e394dbff..360f281bd1e6 100644
--- a/arch/ppc/configs/power3_defconfig
+++ b/arch/ppc/configs/power3_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
diff --git a/arch/ppc/configs/pplus_defconfig b/arch/ppc/configs/pplus_defconfig
index 8dfa789c9939..ff29c2bae2be 100644
--- a/arch/ppc/configs/pplus_defconfig
+++ b/arch/ppc/configs/pplus_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PPLUS=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_ALTIVEC is not set
diff --git a/arch/ppc/configs/prpmc750_defconfig b/arch/ppc/configs/prpmc750_defconfig
index 24c993675118..6500b795e2b4 100644
--- a/arch/ppc/configs/prpmc750_defconfig
+++ b/arch/ppc/configs/prpmc750_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PRPMC750=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_ALTIVEC is not set
diff --git a/arch/ppc/configs/prpmc800_defconfig b/arch/ppc/configs/prpmc800_defconfig
index ee07a3c5ebb3..7aa5e0cf3acd 100644
--- a/arch/ppc/configs/prpmc800_defconfig
+++ b/arch/ppc/configs/prpmc800_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_PRPMC800=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
# CONFIG_ALTIVEC is not set
diff --git a/arch/ppc/configs/sandpoint_defconfig b/arch/ppc/configs/sandpoint_defconfig
index a7b1f4bbbf00..74cf67dfe485 100644
--- a/arch/ppc/configs/sandpoint_defconfig
+++ b/arch/ppc/configs/sandpoint_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,8 +66,7 @@ CONFIG_SANDPOINT=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
-CONFIG_SANDPOINT_X3=y
+CONFIG_PPC_GEN550=y
CONFIG_EPIC_SERIAL_MODE=y
# CONFIG_MPC10X_STORE_GATHERING is not set
# CONFIG_SMP is not set
@@ -84,8 +82,8 @@ CONFIG_ALTIVEC=y
CONFIG_PCI=y
CONFIG_PCI_DOMAINS=y
CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
CONFIG_KERNEL_ELF=y
+CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
@@ -118,6 +116,11 @@ CONFIG_TASK_SIZE=0x80000000
CONFIG_BOOT_LOAD=0x00800000
#
+# Generic Driver Options
+#
+# CONFIG_FW_LOADER is not set
+
+#
# Memory Technology Devices (MTD)
#
# CONFIG_MTD is not set
@@ -147,7 +150,7 @@ CONFIG_BLK_DEV_INITRD=y
# CONFIG_MD is not set
#
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
#
CONFIG_IDE=y
@@ -166,6 +169,7 @@ CONFIG_BLK_DEV_IDEDISK=y
CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEFLOPPY is not set
# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_TASKFILE_IO=y
#
# IDE chipset support/bugfixes
@@ -173,7 +177,7 @@ CONFIG_BLK_DEV_IDECD=y
# CONFIG_BLK_DEV_IDEPCI is not set
#
-# SCSI support
+# SCSI device support
#
# CONFIG_SCSI is not set
@@ -292,6 +296,7 @@ CONFIG_NET_PCI=y
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
+# CONFIG_TC35815 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
@@ -413,11 +418,6 @@ CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
# Input device support
#
CONFIG_INPUT=y
@@ -443,6 +443,7 @@ CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
#
# Input Device Drivers
@@ -731,6 +732,7 @@ CONFIG_USB_SE401=m
#
# USB Network adaptors
#
+# CONFIG_USB_AX8817X is not set
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
# CONFIG_USB_PEGASUS is not set
diff --git a/arch/ppc/configs/spruce_defconfig b/arch/ppc/configs/spruce_defconfig
index 4a5a09f95060..7b0c4e560306 100644
--- a/arch/ppc/configs/spruce_defconfig
+++ b/arch/ppc/configs/spruce_defconfig
@@ -55,7 +55,6 @@ CONFIG_PPC_STD_MMU=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
CONFIG_SPRUCE=y
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -67,7 +66,6 @@ CONFIG_SPRUCE=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
# CONFIG_SPRUCE_BAUD_33M is not set
# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
diff --git a/arch/ppc/configs/zx4500_defconfig b/arch/ppc/configs/zx4500_defconfig
deleted file mode 100644
index 8b1bf65a1a50..000000000000
--- a/arch/ppc/configs/zx4500_defconfig
+++ /dev/null
@@ -1,560 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_MMU=y
-CONFIG_RWSEM_XCHGADD_ALGORITHM=y
-CONFIG_HAVE_DEC_LOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EMBEDDED=y
-CONFIG_FUTEX=y
-# CONFIG_EPOLL is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
-
-#
-# Platform support
-#
-CONFIG_PPC=y
-CONFIG_PPC32=y
-CONFIG_6xx=y
-# CONFIG_40x is not set
-# CONFIG_POWER3 is not set
-# CONFIG_8xx is not set
-
-#
-# IBM 4xx options
-#
-# CONFIG_8260 is not set
-CONFIG_GENERIC_ISA_DMA=y
-CONFIG_PPC_STD_MMU=y
-# CONFIG_PPC_MULTIPLATFORM is not set
-# CONFIG_APUS is not set
-# CONFIG_WILLOW_2 is not set
-# CONFIG_PCORE is not set
-# CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
-# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
-# CONFIG_LOPEC is not set
-# CONFIG_MCPN765 is not set
-# CONFIG_MVME5100 is not set
-# CONFIG_PPLUS is not set
-# CONFIG_PRPMC750 is not set
-# CONFIG_PRPMC800 is not set
-# CONFIG_SANDPOINT is not set
-# CONFIG_ADIR is not set
-# CONFIG_K2 is not set
-# CONFIG_PAL4 is not set
-# CONFIG_GEMINI is not set
-CONFIG_ZX4500=y
-# CONFIG_MPC10X_STORE_GATHERING is not set
-# CONFIG_SMP is not set
-# CONFIG_PREEMPT is not set
-# CONFIG_ALTIVEC is not set
-# CONFIG_TAU is not set
-# CONFIG_CPU_FREQ is not set
-
-#
-# General setup
-#
-# CONFIG_HIGHMEM is not set
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_KCORE_ELF=y
-CONFIG_BINFMT_ELF=y
-CONFIG_KERNEL_ELF=y
-CONFIG_BINFMT_MISC=y
-# CONFIG_PCI_LEGACY_PROC is not set
-CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-CONFIG_PPC601_SYNC_FIX=y
-# CONFIG_CMDLINE_BOOL is not set
-
-#
-# Advanced setup
-#
-# CONFIG_ADVANCED_OPTIONS is not set
-
-#
-# Default settings for advanced configuration options are used
-#
-CONFIG_HIGHMEM_START=0xfe000000
-CONFIG_LOWMEM_SIZE=0x30000000
-CONFIG_KERNEL_START=0xc0000000
-CONFIG_TASK_SIZE=0x80000000
-CONFIG_BOOT_LOAD=0x00800000
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNP is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_NBD=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_BLK_DEV_INITRD=y
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI support
-#
-# CONFIG_SCSI is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-# CONFIG_NETFILTER is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_XFRM_USER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-CONFIG_IPV6_SCTP__=y
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_OAKNET is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_EEPRO100_PIO is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices (depends on LLC=y)
-#
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN_BOOL is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Userland interfaces
-#
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-
-#
-# Macintosh device drivers
-#
-
-#
-# Character devices
-#
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# I2C Hardware Sensors Mainboard support
-#
-
-#
-# I2C Hardware Sensors Chip support
-#
-# CONFIG_I2C_SENSOR is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-CONFIG_GEN_RTC=y
-# CONFIG_GEN_RTC_X is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_FS_XATTR=y
-# CONFIG_EXT3_FS_POSIX_ACL is not set
-# CONFIG_EXT3_FS_SECURITY is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
-CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_KALLSYMS is not set
-CONFIG_SERIAL_TEXT_DEBUG=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
diff --git a/arch/ppc/defconfig b/arch/ppc/defconfig
index 119106ad7e80..b404c4872d8f 100644
--- a/arch/ppc/defconfig
+++ b/arch/ppc/defconfig
@@ -56,7 +56,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_POWERPMC250 is not set
# CONFIG_EV64260 is not set
# CONFIG_SPRUCE is not set
-# CONFIG_MENF1 is not set
# CONFIG_LOPEC is not set
# CONFIG_MCPN765 is not set
# CONFIG_MVME5100 is not set
@@ -68,7 +67,6 @@ CONFIG_PPC_MULTIPLATFORM=y
# CONFIG_K2 is not set
# CONFIG_PAL4 is not set
# CONFIG_GEMINI is not set
-# CONFIG_ZX4500 is not set
CONFIG_PPC_CHRP=y
CONFIG_PPC_PMAC=y
CONFIG_PPC_PREP=y
diff --git a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c
index acc76c5f264b..0e8be4cb3706 100644
--- a/arch/ppc/kernel/ppc-stub.c
+++ b/arch/ppc/kernel/ppc-stub.c
@@ -851,14 +851,4 @@ kgdb_output_string (const char* s, unsigned int count)
putpacket(buffer);
return 1;
- }
-
-#if defined(CONFIG_6xx) || defined(CONFIG_POWER3)
-
-/* This is used on arches which don't have a serial driver that maps
- * the ports for us */
-void
-kgdb_map_scc(void)
-{
}
-#endif
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 2832d5580c1a..8ef2791d112b 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -272,8 +272,10 @@ EXPORT_SYMBOL(kd_mksound);
#ifdef CONFIG_NVRAM
EXPORT_SYMBOL(nvram_read_byte);
EXPORT_SYMBOL(nvram_write_byte);
+#ifdef CONFIG_PPC_PMAC
EXPORT_SYMBOL(pmac_xpram_read);
EXPORT_SYMBOL(pmac_xpram_write);
+#endif
#endif /* CONFIG_NVRAM */
EXPORT_SYMBOL(to_tm);
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index a0f733b81d09..27be4e413106 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -619,6 +619,8 @@ void __init setup_arch(char **cmdline_p)
if (strstr(cmd_line, "nokgdb"))
printk("kgdb default breakpoint deactivated on command line\n");
else {
+ if (ppc_md.progress)
+ ppc_md.progress("setup_arch: kgdb breakpoint", 0x4000);
printk("kgdb default breakpoint activated\n");
breakpoint();
}
diff --git a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
index 263a40b0563a..9eb9829f3109 100644
--- a/arch/ppc/platforms/Makefile
+++ b/arch/ppc/platforms/Makefile
@@ -43,9 +43,8 @@ obj-$(CONFIG_POWERPMC250) += powerpmc250.o
obj-$(CONFIG_PPLUS) += pplus_pci.o pplus_setup.o
obj-$(CONFIG_PRPMC750) += prpmc750_setup.o prpmc750_pci.o
obj-$(CONFIG_PRPMC800) += prpmc800_setup.o prpmc800_pci.o
-obj-$(CONFIG_SANDPOINT) += sandpoint_setup.o sandpoint_pci.o
+obj-$(CONFIG_SANDPOINT) += sandpoint.o
obj-$(CONFIG_SPRUCE) += spruce_setup.o spruce_pci.o
-obj-$(CONFIG_ZX4500) += zx4500_setup.o zx4500_pci.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o
diff --git a/arch/ppc/platforms/menf1.h b/arch/ppc/platforms/menf1.h
deleted file mode 100644
index ecb9f094ce93..000000000000
--- a/arch/ppc/platforms/menf1.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * arch/ppc/platforms/menf1.h
- *
- * Definitions for MEN F1 board support
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __PPC_PLATFORMS_MENF1_H
-#define __PPC_PLATFORMS_MENF1_H
-
-#define MENF1_NVRAM_AS0 0x70
-#define MENF1_NVRAM_AS1 0x72
-#define MENF1_NVRAM_DATA 0x71
-
-#define MENF1_IDE0_BASE_ADDR 0x1f0
-#define MENF1_IDE1_BASE_ADDR 0x170
-
-#endif /* __PPC_PLATFORMS_MENF1_H */
diff --git a/arch/ppc/platforms/menf1_pci.c b/arch/ppc/platforms/menf1_pci.c
deleted file mode 100644
index 303d8756ffd6..000000000000
--- a/arch/ppc/platforms/menf1_pci.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * arch/ppc/platforms/menf1_pci.c
- *
- * PCI support for MEN F1
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpc10x.h>
-
-#include "menf1.h"
-
-#undef DEBUG
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif /* DEBUG */
-
-static inline int __init
-menf1_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- {10, 11, 7, 9}, /* IDSEL 26 - PCMIP 0 */
- {0, 0, 0, 0}, /* IDSEL 27 - M5229 IDE */
- {0, 0, 0, 0}, /* IDSEL 28 - M7101 PMU */
- {9, 10, 11, 7}, /* IDSEL 29 - PCMIP 1 */
- {10, 11, 7, 9}, /* IDSEL 30 - P2P Bridge */
- };
- const long min_idsel = 26, max_idsel = 30, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-};
-
-static int
-menf1_exclude_device(u_char bus, u_char devfn)
-{
- if ((bus == 0) && (devfn == 0xe0)) {
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- else {
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-void __init
-menf1_find_bridges(void)
-{
- struct pci_controller* hose;
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return;
-
- hose->first_busno = 0;
- hose->last_busno = 0xff;
-
- ppc_md.pci_exclude_device = menf1_exclude_device;
-
- mpc10x_bridge_init(hose,
- MPC10X_MEM_MAP_B,
- MPC10X_MEM_MAP_B,
- MPC10X_MAPB_EUMB_BASE);
-
- hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
- {
- /* Add ISA bus wait states */
- unsigned char isa_control;
-
- early_read_config_byte(hose, 0, 0x90, 0x43, &isa_control);
- isa_control |= 0x33;
- early_write_config_byte(hose, 0, 0x90, 0x43, isa_control);
- }
-
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = menf1_map_irq;
-}
diff --git a/arch/ppc/platforms/menf1_setup.c b/arch/ppc/platforms/menf1_setup.c
deleted file mode 100644
index b202350a7657..000000000000
--- a/arch/ppc/platforms/menf1_setup.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * arch/ppc/platforms/menf1_setup.c
- *
- * Board setup routines for MEN F1
- *
- * Author: Matt Porter <mporter@mvista.com>
- *
- * 2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/i8259.h>
-#include <asm/mpc10x.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-
-#include "menf1.h"
-
-extern void menf1_find_bridges(void);
-extern unsigned long loops_per_jiffy;
-
-/* Dummy variable to satisfy mpc10x_common.o */
-void *OpenPIC_Addr;
-
-static int
-menf1_show_cpuinfo(struct seq_file *m)
-{
- seq_printf(m, "machine\t\t: MEN F1\n");
-
- return 0;
-}
-
-static void __init
-menf1_setup_arch(void)
-{
- /* init to some ~sane value until calibrate_delay() runs */
- loops_per_jiffy = 50000000/HZ;
-
- /* Lookup PCI host bridges */
- menf1_find_bridges();
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA2;
-#endif
-
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
- printk("MEN F1 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
-}
-
-static void
-menf1_restart(char *cmd)
-{
-
- int picr1;
- struct pci_dev *pdev;
-
- local_irq_disable();
-
- /*
- * Firmware doesn't like re-entry using Map B (CHRP), so make sure the
- * PCI bridge is using MAP A (PReP).
- */
-
- pdev = pci_find_slot(0, PCI_DEVFN(0,0));
-
- while(pdev == NULL); /* paranoia */
-
- pci_read_config_dword(pdev, MPC10X_CFG_PICR1_REG, &picr1);
-
- picr1 = (picr1 & ~MPC10X_CFG_PICR1_ADDR_MAP_MASK) |
- MPC10X_CFG_PICR1_ADDR_MAP_A;
-
- pci_write_config_dword(pdev, MPC10X_CFG_PICR1_REG, picr1);
-
- asm volatile("sync");
-
- /* SRR0 has system reset vector, SRR1 has default MSR value */
- /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */
- __asm__ __volatile__
- ("\n\
- lis 3,0xfff0
- ori 3,3,0x0100
- mtspr 26,3
- li 3,0
- mtspr 27,3
- rfi
- ");
- while(1);
-}
-
-static void
-menf1_halt(void)
-{
- local_irq_disable();
- while (1);
-}
-
-static void
-menf1_power_off(void)
-{
- menf1_halt();
-}
-
-static void __init
-menf1_init_IRQ(void)
-{
- int i;
-
- for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
- irq_desc[i].handler = &i8259_pic;
- i8259_init(NULL);
-}
-
-/*
- * Set BAT 3 to map 0xF0000000.
- */
-static __inline__ void
-menf1_set_bat(void)
-{
- static int mapping_set = 0;
-
- if (!mapping_set)
- {
-
- /* wait for all outstanding memory accesses to complete */
- mb();
-
- /* setup DBATs */
- mtspr(DBAT3U, 0xf0001ffe);
- mtspr(DBAT3L, 0xf000002a);
-
- /* wait for updates */
- mb();
-
- mapping_set = 1;
- }
- return;
-}
-
-static unsigned long __init
-menf1_find_end_of_memory(void)
-{
- /* Cover the I/O with a BAT */
- menf1_set_bat();
-
- /* Read the memory size from the MPC107 SMC */
- return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-}
-
-static void __init
-menf1_map_io(void)
-{
- io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/* IDE functions */
-
-static void __init
-menf1_ide_init_hwif_ports (hw_regs_t *hw, unsigned long data_port,
- unsigned long ctrl_port, int *irq)
-{
- unsigned long reg = data_port;
- int i = 8;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg;
- reg += 1;
- }
- if (ctrl_port)
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- else
- hw->io_ports[IDE_CONTROL_OFFSET] =
- hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-
- if (irq != NULL)
- *irq = 0;
-}
-
-static int
-menf1_ide_default_irq(unsigned long base)
-{
- if (base == MENF1_IDE0_BASE_ADDR)
- return 14;
- else if (base == MENF1_IDE1_BASE_ADDR)
- return 15;
- else
- return 0;
-}
-
-static unsigned long
-menf1_ide_default_io_base(int index)
-{
- if (index == 0)
- return MENF1_IDE0_BASE_ADDR;
- else if (index == 1)
- return MENF1_IDE1_BASE_ADDR;
- else
- return 0;
-}
-#endif
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
- isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
- pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-
- ppc_md.setup_arch = menf1_setup_arch;
- ppc_md.show_cpuinfo = menf1_show_cpuinfo;
- ppc_md.init_IRQ = menf1_init_IRQ;
- ppc_md.get_irq = i8259_irq;
-
- ppc_md.find_end_of_memory = menf1_find_end_of_memory;
- ppc_md.setup_io_mappings = menf1_map_io;
-
- ppc_md.restart = menf1_restart;
- ppc_md.power_off = menf1_power_off;
- ppc_md.halt = menf1_halt;
-
- TODC_INIT(TODC_TYPE_MK48T59,
- MENF1_NVRAM_AS0,
- MENF1_NVRAM_AS1,
- MENF1_NVRAM_DATA,
- 7);
-
- ppc_md.time_init = todc_time_init;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.calibrate_decr = todc_calibrate_decr;
-
- ppc_md.nvram_read_val = todc_m48txx_read_val;
- ppc_md.nvram_write_val = todc_m48txx_write_val;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- ppc_ide_md.default_io_base = menf1_ide_default_io_base;
- ppc_ide_md.default_irq = menf1_ide_default_irq;
- ppc_ide_md.ide_init_hwif = menf1_ide_init_hwif_ports;
-#endif
-}
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
new file mode 100644
index 000000000000..5c3e87fd081e
--- /dev/null
+++ b/arch/ppc/platforms/sandpoint.c
@@ -0,0 +1,719 @@
+/*
+ * arch/ppc/platforms/sandpoint_setup.c
+ *
+ * Board setup routines for the Motorola SPS Sandpoint Test Platform.
+ *
+ * Author: Mark A. Greer
+ * mgreer@mvista.com
+ *
+ * 2000-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+/*
+ * This file adds support for the Motorola SPS Sandpoint Test Platform.
+ * These boards have a PPMC slot for the processor so any combination
+ * of cpu and host bridge can be attached. This port is for an 8240 PPMC
+ * module from Motorola SPS and other closely related cpu/host bridge
+ * combinations (e.g., 750/755/7400 with MPC107 host bridge).
+ * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
+ * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
+ * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
+ * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
+ * but are really 5V).
+ *
+ * The firmware on the sandpoint is called DINK (not my acronym :). This port
+ * depends on DINK to do some basic initialization (e.g., initialize the memory
+ * ctlr) and to ensure that the processor is using MAP B (CHRP map).
+ *
+ * The switch settings for the Sandpoint board MUST be as follows:
+ * S3: down
+ * S4: up
+ * S5: up
+ * S6: down
+ *
+ * 'down' is in the direction from the PCI slots towards the PPMC slot;
+ * 'up' is in the direction from the PPMC slot towards the PCI slots.
+ * Be careful, the way the sandpoint board is installed in XT chasses will
+ * make the directions reversed.
+ *
+ * Since Motorola listened to our suggestions for improvement, we now have
+ * the Sandpoint X3 board. All of the PCI slots are available, it uses
+ * the serial interrupt interface (just a hardware thing we need to
+ * configure properly).
+ *
+ * Use the default X3 switch settings. The interrupts are then:
+ * EPIC Source
+ * 0 SIOINT (8259, active low)
+ * 1 PCI #1
+ * 2 PCI #2
+ * 3 PCI #3
+ * 4 PCI #4
+ * 7 Winbond INTC (IDE interrupt)
+ * 8 Winbond INTD (IDE interrupt)
+ *
+ *
+ * Motorola has finally released a version of DINK32 that correctly
+ * (seemingly) initalizes the memory controller correctly, regardless
+ * of the amount of memory in the system. Once a method of determining
+ * what version of DINK initializes the system for us, if applicable, is
+ * found, we can hopefully stop hardcoding 32MB of RAM.
+ *
+ * It is important to note that this code only supports the Sandpoint X3
+ * (all flavors) platform, and it does not support the X2 anymore. Code
+ * that at one time worked on the X2 can be found at:
+ * ftp://source.mvista.com/pub/linuxppc/obsolete/sandpoint/
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h> /* for linux/serial_core.h */
+#include <linux/serial_core.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+
+#include "sandpoint.h"
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+unsigned char __res[sizeof(bd_t)];
+
+static void sandpoint_halt(void);
+
+/*
+ * Define all of the IRQ senses and polarities. Taken from the
+ * Sandpoint X3 User's manual.
+ */
+static u_char sandpoint_openpic_initsenses[] __initdata = {
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 0: SIOINT */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 2: PCI Slot 1 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 3: PCI Slot 2 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 4: PCI Slot 3 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 5: PCI Slot 4 */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* 8: IDE (INT C) */
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE) /* 9: IDE (INT D) */
+};
+
+/*
+ * Motorola SPS Sandpoint interrupt routing.
+ */
+static inline int
+sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
+{
+ static char pci_irq_table[][4] =
+ /*
+ * PCI IDSEL/INTPIN->INTLINE
+ * A B C D
+ */
+ {
+ { 16, 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
+ { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
+ { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
+ { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
+ { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
+ { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
+ };
+
+ const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void __init
+sandpoint_setup_winbond_83553(struct pci_controller *hose)
+{
+ int devfn;
+
+ /*
+ * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
+ * We can't route the IDE interrupt to PCI INTC# or INTD# because those
+ * woule interfere with the PMC's INTC# and INTD# lines.
+ */
+ /*
+ * Winbond Fcn 0
+ */
+ devfn = PCI_DEVFN(11,0);
+
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x43, /* IDE Interrupt Routing Control */
+ 0xef);
+ early_write_config_word(hose,
+ 0,
+ devfn,
+ 0x44, /* PCI Interrupt Routing Control */
+ 0x0000);
+
+ /* Want ISA memory cycles to be forwarded to PCI bus */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x48, /* ISA-to-PCI Addr Decoder Control */
+ 0xf0);
+
+ /* Enable RTC and Keyboard address locations. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x4d, /* Chip Select Control Register */
+ 0x00);
+
+ /* Enable Port 92. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x4e, /* AT System Control Register */
+ 0x06);
+ /*
+ * Winbond Fcn 1
+ */
+ devfn = PCI_DEVFN(11,1);
+
+ /* Put IDE controller into native mode. */
+ early_write_config_byte(hose,
+ 0,
+ devfn,
+ 0x09, /* Programming interface Register */
+ 0x8f);
+
+ /* Init IRQ routing, enable both ports, disable fast 16 */
+ early_write_config_dword(hose,
+ 0,
+ devfn,
+ 0x40, /* IDE Control/Status Register */
+ 0x00ff0011);
+ return;
+}
+
+static void __init
+sandpoint_find_bridges(void)
+{
+ struct pci_controller *hose;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+
+ if (mpc10x_bridge_init(hose,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MEM_MAP_B,
+ MPC10X_MAPB_EUMB_BASE) == 0) {
+
+ /* Do early winbond init, then scan PCI bus */
+ sandpoint_setup_winbond_83553(hose);
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_bus = NULL;
+ ppc_md.pci_swizzle = common_swizzle;
+ ppc_md.pci_map_irq = sandpoint_map_irq;
+ }
+ else {
+ if (ppc_md.progress)
+ ppc_md.progress("Bridge init failed", 0x100);
+ printk("Host bridge init failed\n");
+ }
+
+ return;
+}
+
+#if defined(CONFIG_SERIAL_8250) && \
+ (defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
+static void __init
+sandpoint_early_serial_map(void)
+{
+ struct uart_port serial_req;
+
+ /* Setup serial port access */
+ memset(&serial_req, 0, sizeof(serial_req));
+ serial_req.uartclk = UART_CLK;
+ serial_req.irq = 4;
+ serial_req.flags = STD_COM_FLAGS;
+ serial_req.iotype = SERIAL_IO_MEM;
+ serial_req.membase = (u_char *)SANDPOINT_SERIAL_0;
+
+ gen550_init(0, &serial_req);
+
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+ /* Assume early_serial_setup() doesn't modify serial_req */
+ serial_req.line = 1;
+ serial_req.irq = 3; /* XXXX */
+ serial_req.membase = (u_char *)SANDPOINT_SERIAL_1;
+
+ gen550_init(1, &serial_req);
+
+ if (early_serial_setup(&serial_req) != 0)
+ printk(KERN_ERR "Early serial init of port 1 failed\n");
+}
+#endif
+
+static void __init
+sandpoint_setup_arch(void)
+{
+ loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start)
+ ROOT_DEV = Root_RAM0;
+ else
+#endif
+#ifdef CONFIG_ROOT_NFS
+ ROOT_DEV = Root_NFS;
+#else
+ ROOT_DEV = Root_HDA1;
+#endif
+
+ /* Lookup PCI host bridges */
+ sandpoint_find_bridges();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
+ printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
+
+ /* DINK32 12.3 and below do not correctly enable any caches.
+ * We will do this now with good known values. Future versions
+ * of DINK32 are supposed to get this correct.
+ */
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450)
+ /* 745x is different. We only want to pass along enable. */
+ _set_L2CR(L2CR_L2E);
+ else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+ /* All modules have 1MB of L2. We also assume that an
+ * L2 divisor of 3 will work.
+ */
+ _set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+ | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+#if 0
+ /* Untested right now. */
+ if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) {
+ /* Magic value. */
+ _set_L3CR(0x8f032000);
+ }
+#endif
+}
+
+#define SANDPOINT_87308_CFG_ADDR 0x15c
+#define SANDPOINT_87308_CFG_DATA 0x15d
+
+#define SANDPOINT_87308_CFG_INB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ (byte) = inb(SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_CFG_OUTB(addr, byte) { \
+ outb((addr), SANDPOINT_87308_CFG_ADDR); \
+ outb((byte), SANDPOINT_87308_CFG_DATA); \
+}
+
+#define SANDPOINT_87308_SELECT_DEV(dev_num) { \
+ SANDPOINT_87308_CFG_OUTB(0x07, (dev_num)); \
+}
+
+#define SANDPOINT_87308_DEV_ENABLE(dev_num) { \
+ SANDPOINT_87308_SELECT_DEV(dev_num); \
+ SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
+}
+
+/*
+ * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
+ */
+static int __init
+sandpoint_setup_natl_87308(void)
+{
+ u_char reg;
+
+ /*
+ * Enable all the devices on the Super I/O chip.
+ */
+ SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
+ SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
+ SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
+ SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
+ SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
+ SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
+ SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+ SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
+ SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
+
+ /* Set up floppy in PS/2 mode */
+ outb(0x09, SIO_CONFIG_RA);
+ reg = inb(SIO_CONFIG_RD);
+ reg = (reg & 0x3F) | 0x40;
+ outb(reg, SIO_CONFIG_RD);
+ outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
+
+ return 0;
+}
+
+arch_initcall(sandpoint_setup_natl_87308);
+
+/*
+ * Fix IDE interrupts.
+ */
+static int __init
+sandpoint_fix_winbond_83553(void)
+{
+ /* Make all 8259 interrupt level sensitive */
+ outb(0xf8, 0x4d0);
+ outb(0xde, 0x4d1);
+
+ return 0;
+}
+
+arch_initcall(sandpoint_fix_winbond_83553);
+
+static int __init
+sandpoint_request_io(void)
+{
+ request_region(0x00,0x20,"dma1");
+ request_region(0x20,0x20,"pic1");
+ request_region(0x40,0x20,"timer");
+ request_region(0x80,0x10,"dma page reg");
+ request_region(0xa0,0x20,"pic2");
+ request_region(0xc0,0x20,"dma2");
+
+ return 0;
+}
+
+arch_initcall(sandpoint_request_io);
+
+/*
+ * Interrupt setup and service. Interrrupts on the Sandpoint come
+ * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
+ * The 8259 is cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4,
+ * IDE is on EPIC 7 and 8.
+ */
+static void __init
+sandpoint_init_IRQ(void)
+{
+ int i;
+
+ OpenPIC_InitSenses = sandpoint_openpic_initsenses;
+ OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
+
+ /*
+ * We need to tell openpic_set_sources where things actually are.
+ * mpc10x_common will setup OpenPIC_Addr at ioremap(EUMB phys base +
+ * EPIC offset (0x40000)); The EPIC IRQ Register Address Map -
+ * Interrupt Source Configuration Registers gives these numbers
+ * as offsets starting at 0x50200, we need to adjust occordinly.
+ */
+ /* Map serial interrupts 0-15 */
+ openpic_set_sources(0, 16, OpenPIC_Addr + 0x10200);
+
+ openpic_init(NUM_8259_INTERRUPTS);
+
+ /*
+ * openpic_init() has set up irq_desc[16-31] to be openpic
+ * interrupts. We need to set irq_desc[0-15] to be i8259
+ * interrupts.
+ */
+ for(i=0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ /*
+ * The EPIC allows for a read in the range of 0xFEF00000 ->
+ * 0xFEFFFFFF to generate a PCI interrupt-acknowledge transaction.
+ */
+ i8259_init(0xfef00000);
+}
+
+static u32
+sandpoint_irq_canonicalize(u32 irq)
+{
+ if (irq == 2)
+ return 9;
+ else
+ return irq;
+}
+
+static unsigned long __init
+sandpoint_find_end_of_memory(void)
+{
+ bd_t *bp = (bd_t *)__res;
+
+ if (bp->bi_memsize)
+ return bp->bi_memsize;
+
+ /* DINK32 13.0 correctly initalizes things, so iff you use
+ * this you _should_ be able to change this instead of a
+ * hardcoded value. */
+#if 0
+ return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
+#else
+ return 32*1024*1024;
+#endif
+}
+
+static void __init
+sandpoint_map_io(void)
+{
+ io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void
+sandpoint_restart(char *cmd)
+{
+ local_irq_disable();
+
+ /* Set exception prefix high - to the firmware */
+ _nmask_and_or_msr(0, MSR_IP);
+
+ /* Reset system via Port 92 */
+ outb(0x00, 0x92);
+ outb(0x01, 0x92);
+ for(;;); /* Spin until reset happens */
+}
+
+static void
+sandpoint_power_off(void)
+{
+ local_irq_disable();
+ for(;;); /* No way to shut power off with software */
+ /* NOTREACHED */
+}
+
+static void
+sandpoint_halt(void)
+{
+ sandpoint_power_off();
+ /* NOTREACHED */
+}
+
+static int
+sandpoint_show_cpuinfo(struct seq_file *m)
+{
+ seq_printf(m, "vendor\t\t: Motorola SPS\n");
+ seq_printf(m, "machine\t\t: Sandpoint\n");
+
+ return 0;
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE support.
+ */
+static int sandpoint_ide_ports_known = 0;
+static unsigned long sandpoint_ide_regbase[MAX_HWIFS];
+static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS];
+static unsigned long sandpoint_idedma_regbase;
+
+static void
+sandpoint_ide_probe(void)
+{
+ struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+ PCI_DEVICE_ID_WINBOND_82C105, NULL);
+
+ if (pdev) {
+ sandpoint_ide_regbase[0]=pdev->resource[0].start;
+ sandpoint_ide_regbase[1]=pdev->resource[2].start;
+ sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
+ sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
+ sandpoint_idedma_regbase=pdev->resource[4].start;
+ }
+
+ sandpoint_ide_ports_known = 1;
+}
+
+static int
+sandpoint_ide_default_irq(unsigned long base)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ if (base == sandpoint_ide_regbase[0])
+ return SANDPOINT_IDE_INT0;
+ else if (base == sandpoint_ide_regbase[1])
+ return SANDPOINT_IDE_INT1;
+ else
+ return 0;
+}
+
+static unsigned long
+sandpoint_ide_default_io_base(int index)
+{
+ if (sandpoint_ide_ports_known == 0)
+ sandpoint_ide_probe();
+
+ return sandpoint_ide_regbase[index];
+}
+
+static void __init
+sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
+ unsigned long ctrl_port, int *irq)
+{
+ unsigned long reg = data_port;
+ uint alt_status_base;
+ int i;
+
+ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+ hw->io_ports[i] = reg++;
+ }
+
+ if (data_port == sandpoint_ide_regbase[0]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
+ hw->irq = 14;
+ }
+ else if (data_port == sandpoint_ide_regbase[1]) {
+ alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
+ hw->irq = 15;
+ }
+ else {
+ alt_status_base = 0;
+ hw->irq = 0;
+ }
+
+ if (ctrl_port) {
+ hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+ } else {
+ hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
+ }
+
+ if (irq != NULL) {
+ *irq = hw->irq;
+ }
+}
+#endif
+
+/*
+ * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
+ */
+static __inline__ void
+sandpoint_set_bat(void)
+{
+ unsigned long bat3u, bat3l;
+
+ __asm__ __volatile__(
+ " lis %0,0xf800\n \
+ ori %1,%0,0x002a\n \
+ ori %0,%0,0x0ffe\n \
+ mtspr 0x21e,%0\n \
+ mtspr 0x21f,%1\n \
+ isync\n \
+ sync "
+ : "=r" (bat3u), "=r" (bat3l));
+}
+
+TODC_ALLOC();
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+ unsigned long r6, unsigned long r7)
+{
+ parse_bootinfo(find_bootinfo());
+
+ /* ASSUMPTION: If both r3 (bd_t pointer) and r6 (cmdline pointer)
+ * are non-zero, then we should use the board info from the bd_t
+ * structure and the cmdline pointed to by r6 instead of the
+ * information from birecs, if any. Otherwise, use the information
+ * from birecs as discovered by the preceeding call to
+ * parse_bootinfo(). This rule should work with both PPCBoot, which
+ * uses a bd_t board info structure, and the kernel boot wrapper,
+ * which uses birecs.
+ */
+ if (r3 && r6) {
+ /* copy board info structure */
+ memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+ /* copy command line */
+ *(char *)(r7+KERNELBASE) = 0;
+ strcpy(cmd_line, (char *)(r6+KERNELBASE));
+ }
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ /* take care of initrd if we have one */
+ if (r4) {
+ initrd_start = r4 + KERNELBASE;
+ initrd_end = r5 + KERNELBASE;
+ }
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+ /* Map in board regs, etc. */
+ sandpoint_set_bat();
+
+ isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
+ isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
+ pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
+ ISA_DMA_THRESHOLD = 0x00ffffff;
+ DMA_MODE_READ = 0x44;
+ DMA_MODE_WRITE = 0x48;
+
+ ppc_md.setup_arch = sandpoint_setup_arch;
+ ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
+ ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
+ ppc_md.init_IRQ = sandpoint_init_IRQ;
+ ppc_md.get_irq = openpic_get_irq;
+
+ ppc_md.restart = sandpoint_restart;
+ ppc_md.power_off = sandpoint_power_off;
+ ppc_md.halt = sandpoint_halt;
+
+ ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
+ ppc_md.setup_io_mappings = sandpoint_map_io;
+
+ TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
+ ppc_md.time_init = todc_time_init;
+ ppc_md.set_rtc_time = todc_set_rtc_time;
+ ppc_md.get_rtc_time = todc_get_rtc_time;
+ ppc_md.calibrate_decr = todc_calibrate_decr;
+
+ ppc_md.nvram_read_val = todc_mc146818_read_val;
+ ppc_md.nvram_write_val = todc_mc146818_write_val;
+
+#if defined(CONFIG_SERIAL_8250) && \
+ (defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG))
+ sandpoint_early_serial_map();
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+ ppc_md.progress = gen550_progress;
+#endif
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+ ppc_ide_md.default_irq = sandpoint_ide_default_irq;
+ ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
+ ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
+#endif
+}
diff --git a/arch/ppc/platforms/sandpoint.h b/arch/ppc/platforms/sandpoint.h
index e1a5b36c5de4..bdb7fb83f155 100644
--- a/arch/ppc/platforms/sandpoint.h
+++ b/arch/ppc/platforms/sandpoint.h
@@ -6,7 +6,7 @@
* Author: Mark A. Greer
* mgreer@mvista.com
*
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
+ * 2000-2003 (c) MontaVista, Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
@@ -19,8 +19,8 @@
#ifndef __PPC_PLATFORMS_SANDPOINT_H
#define __PPC_PLATFORMS_SANDPOINT_H
-#ifdef CONFIG_SANDPOINT_X3
-#define SANDPOINT_SIO_SLOT 0 /* Cascaded from EPIC IRQ 0 */
+#include <asm/ppcboot.h>
+
#if 0
/* The Sandpoint X3 allows the IDE interrupt to be directly connected
* from the Windbond (PCI INTC or INTD) to the serial EPIC. Someday
@@ -28,27 +28,13 @@
* initialization than change it to route the different interrupts :-).
* -- Dan
*/
-#define SANDPOINT_IDE_INT0 23 /* EPIC 7 */
-#define SANDPOINT_IDE_INT1 24 /* EPIC 8 */
-#else
-#define SANDPOINT_IDE_INT0 14 /* 8259 Test */
-#define SANDPOINT_IDE_INT1 15 /* 8259 Test */
-#endif
+#define SANDPOINT_IDE_INT0 23 /* EPIC 7 */
+#define SANDPOINT_IDE_INT1 24 /* EPIC 8 */
#else
- /*
- * Define the PCI slot that the 8259 is sharing interrupts with.
- * Valid values are 1 (PCI slot 2) and 2 (PCI slot 3).
- */
-#define SANDPOINT_SIO_SLOT 1
-
-/* ...and for the IDE from the 8259....
-*/
-#define SANDPOINT_IDE_INT0 14
-#define SANDPOINT_IDE_INT1 15
+#define SANDPOINT_IDE_INT0 14 /* 8259 Test */
+#define SANDPOINT_IDE_INT1 15 /* 8259 Test */
#endif
-#define SANDPOINT_SIO_IRQ (SANDPOINT_SIO_SLOT + NUM_8259_INTERRUPTS)
-
/*
* The sandpoint boards have processor modules that either have an 8240 or
* an MPC107 host bridge on them. These bridges have an IDSEL line that allows
@@ -62,7 +48,33 @@
*/
#define SANDPOINT_HOST_BRIDGE_IDSEL 12
+/*
+ * Serial defines.
+ */
+#define SANDPOINT_SERIAL_0 0xfe0003f8
+#define SANDPOINT_SERIAL_1 0xfe0002f8
+
+#define RS_TABLE_SIZE 2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define BASE_BAUD ( 1843200 / 16 )
+#define UART_CLK 1843200
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+ { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+ iomem_base: (u8 *)SANDPOINT_SERIAL_0, \
+ io_type: SERIAL_IO_MEM }, \
+ { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+ iomem_base: (u8 *)SANDPOINT_SERIAL_1, \
+ io_type: SERIAL_IO_MEM },
-void sandpoint_find_bridges(void);
+#define SERIAL_PORT_DFNS \
+ STD_SERIAL_PORT_DFNS
#endif /* __PPC_PLATFORMS_SANDPOINT_H */
diff --git a/arch/ppc/platforms/sandpoint_pci.c b/arch/ppc/platforms/sandpoint_pci.c
deleted file mode 100644
index e585637f05f4..000000000000
--- a/arch/ppc/platforms/sandpoint_pci.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * arch/ppc/platforms/sandpoint_pci.c
- *
- * PCI setup routines for the Motorola SPS Sandpoint Test Platform
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpc10x.h>
-
-#include "sandpoint.h"
-
-/*
- * Motorola SPS Sandpoint interrupt routing.
- */
-static inline int
-sandpoint_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- { SANDPOINT_SIO_IRQ,
- 0, 0, 0 }, /* IDSEL 11 - i8259 on Winbond */
- { 0, 0, 0, 0 }, /* IDSEL 12 - unused */
-#ifdef CONFIG_SANDPOINT_X3
-#if 0 /* This is what it _should_ look like -- Dan */
- { 17, 20, 19, 18 }, /* IDSEL 13 - PCI slot 1 */
- { 18, 17, 20, 19 }, /* IDSEL 14 - PCI slot 2 */
- { 19, 18, 17, 20 }, /* IDSEL 15 - PCI slot 3 */
- { 20, 19, 18, 17 }, /* IDSEL 16 - PCI slot 4 */
-#else
- { 18, 21, 20, 19 }, /* IDSEL 13 - PCI slot 1 */
- { 19, 18, 21, 20 }, /* IDSEL 14 - PCI slot 2 */
- { 20, 19, 18, 21 }, /* IDSEL 15 - PCI slot 3 */
- { 21, 20, 19, 18 }, /* IDSEL 16 - PCI slot 4 */
-#endif
-#else
- { 16, 19, 18, 17 }, /* IDSEL 13 - PCI slot 1 */
- { 17, 16, 19, 18 }, /* IDSEL 14 - PCI slot 2 */
- { 18, 17, 16, 19 }, /* IDSEL 15 - PCI slot 3 */
- { 19, 18, 17, 16 }, /* IDSEL 16 - PCI slot 4 */
-#endif
- };
-
- const long min_idsel = 11, max_idsel = 16, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-
-static void __init
-sandpoint_setup_winbond_83553(struct pci_controller *hose)
-{
- int devfn;
-
- /*
- * Route IDE interrupts directly to the 8259's IRQ 14 & 15.
- * We can't route the IDE interrupt to PCI INTC# or INTD# because those
- * woule interfere with the PMC's INTC# and INTD# lines.
- */
- /*
- * Winbond Fcn 0
- */
- devfn = PCI_DEVFN(11,0);
-
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x43, /* IDE Interrupt Routing Control */
- 0xef);
- early_write_config_word(hose,
- 0,
- devfn,
- 0x44, /* PCI Interrupt Routing Control */
- 0x0000);
-
- /* Want ISA memory cycles to be forwarded to PCI bus */
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x48, /* ISA-to-PCI Addr Decoder Control */
- 0xf0);
-
- /* Enable RTC and Keyboard address locations. */
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x4d, /* Chip Select Control Register */
- 0x00);
-
- /* Enable Port 92. */
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x4e, /* AT System Control Register */
- 0x06);
- /*
- * Winbond Fcn 1
- */
- devfn = PCI_DEVFN(11,1);
-
- /* Put IDE controller into native mode. */
- early_write_config_byte(hose,
- 0,
- devfn,
- 0x09, /* Programming interface Register */
- 0x8f);
-
- /* Init IRQ routing, enable both ports, disable fast 16 */
- early_write_config_dword(hose,
- 0,
- devfn,
- 0x40, /* IDE Control/Status Register */
- 0x00ff0011);
- return;
-}
-
-static int
-sandpoint_exclude_device(u_char bus, u_char devfn)
-{
- if ((bus == 0) && (PCI_SLOT(devfn) == SANDPOINT_HOST_BRIDGE_IDSEL)) {
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- else {
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-void __init
-sandpoint_find_bridges(void)
-{
- struct pci_controller *hose;
-
- hose = pcibios_alloc_controller();
-
- if (!hose)
- return;
-
- hose->first_busno = 0;
- hose->last_busno = 0xff;
-
- if (mpc10x_bridge_init(hose,
- MPC10X_MEM_MAP_B,
- MPC10X_MEM_MAP_B,
- MPC10X_MAPB_EUMB_BASE) == 0) {
-
- /* Do early winbond init, then scan PCI bus */
- sandpoint_setup_winbond_83553(hose);
- ppc_md.pci_exclude_device = sandpoint_exclude_device;
- hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
- ppc_md.pcibios_fixup = NULL;
- ppc_md.pcibios_fixup_bus = NULL;
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = sandpoint_map_irq;
- }
- else {
- if (ppc_md.progress)
- ppc_md.progress("Bridge init failed", 0x100);
- printk("Host bridge init failed\n");
- }
-
- return;
-}
diff --git a/arch/ppc/platforms/sandpoint_serial.h b/arch/ppc/platforms/sandpoint_serial.h
deleted file mode 100644
index 0981c415fa57..000000000000
--- a/arch/ppc/platforms/sandpoint_serial.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * include/asm-ppc/sandpoint_serial.h
- *
- * Definitions for Motorola SPS Sandpoint Test Platform
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_SANDPOINT_SERIAL_H
-#define __ASMPPC_SANDPOINT_SERIAL_H
-
-#include <linux/config.h>
-
-#define SANDPOINT_SERIAL_0 0xfe0003f8
-#define SANDPOINT_SERIAL_1 0xfe0002f8
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE 64
-#else
-#define RS_TABLE_SIZE 2
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define STD_SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, SANDPOINT_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
- iomem_base: (u8 *)SANDPOINT_SERIAL_0, \
- io_type: SERIAL_IO_MEM }, \
- { 0, BASE_BAUD, SANDPOINT_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
- iomem_base: (u8 *)SANDPOINT_SERIAL_1, \
- io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
- STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_SANDPOINT_SERIAL_H */
diff --git a/arch/ppc/platforms/sandpoint_setup.c b/arch/ppc/platforms/sandpoint_setup.c
deleted file mode 100644
index 5860f3d0adef..000000000000
--- a/arch/ppc/platforms/sandpoint_setup.c
+++ /dev/null
@@ -1,643 +0,0 @@
-/*
- * arch/ppc/platforms/sandpoint_setup.c
- *
- * Board setup routines for the Motorola SPS Sandpoint Test Platform.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * This file adds support for the Motorola SPS Sandpoint Test Platform.
- * These boards have a PPMC slot for the processor so any combination
- * of cpu and host bridge can be attached. This port is for an 8240 PPMC
- * module from Motorola SPS and other closely related cpu/host bridge
- * combinations (e.g., 750/755/7400 with MPC107 host bridge).
- * The sandpoint itself has a Windbond 83c553 (PCI-ISA bridge, 2 DMA ctlrs, 2
- * cascaded 8259 interrupt ctlrs, 8254 Timer/Counter, and an IDE ctlr), a
- * National 87308 (RTC, 2 UARTs, Keyboard & mouse ctlrs, and a floppy ctlr),
- * and 4 PCI slots (only 2 of which are usable; the other 2 are keyed for 3.3V
- * but are really 5V).
- *
- * The firmware on the sandpoint is called DINK (not my acronym :). This port
- * depends on DINK to do some basic initialization (e.g., initialize the memory
- * ctlr) and to ensure that the processor is using MAP B (CHRP map).
- *
- * The switch settings for the Sandpoint board MUST be as follows:
- * S3: down
- * S4: up
- * S5: up
- * S6: down
- *
- * 'down' is in the direction from the PCI slots towards the PPMC slot;
- * 'up' is in the direction from the PPMC slot towards the PCI slots.
- * Be careful, the way the sandpoint board is installed in XT chasses will
- * make the directions reversed.
- *
- * Since Motorola listened to our suggestions for improvement, we now have
- * the Sandpoint X3 board. All of the PCI slots are available, it uses
- * the serial interrupt interface (just a hardware thing we need to
- * configure properly).
- *
- * Use the default X3 switch settings. The interrupts are then:
- * EPIC Source
- * 0 SIOINT (8259, active low)
- * 1 PCI #1
- * 2 PCI #2
- * 3 PCI #3
- * 4 PCI #4
- * 7 Winbond INTC (IDE interrupt)
- * 8 Winbond INTD (IDE interrupt)
- *
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/time.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/vga.h>
-#include <asm/open_pic.h>
-#include <asm/i8259.h>
-#include <asm/todc.h>
-#include <asm/bootinfo.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-
-#include "sandpoint.h"
-
-extern u_int openpic_irq(void);
-extern void openpic_eoi(void);
-
-static void sandpoint_halt(void);
-
-
-/*
- * *** IMPORTANT ***
- *
- * The first 16 entries of 'sandpoint_openpic_initsenses[]' are there and
- * initialized to 0 on purpose. DO NOT REMOVE THEM as the 'offset' parameter
- * of 'openpic_init()' does not work for the sandpoint because the 8259
- * interrupt is NOT routed to the EPIC's IRQ 0 AND the EPIC's IRQ 0's offset is
- * the same as a normal openpic's IRQ 16 offset.
- */
-static u_char sandpoint_openpic_initsenses[] __initdata = {
- 0, /* 0-15 not used by EPCI but by 8259 (std PC-type IRQs) */
- 0, /* 1 */
- 0, /* 2 */
- 0, /* 3 */
- 0, /* 4 */
- 0, /* 5 */
- 0, /* 6 */
- 0, /* 7 */
- 0, /* 8 */
- 0, /* 9 */
- 0, /* 10 */
- 0, /* 11 */
- 0, /* 12 */
- 0, /* 13 */
- 0, /* 14 */
- 0, /* 15 */
-#ifdef CONFIG_SANDPOINT_X3
- 1, /* 16: EPIC IRQ 0: Active Low -- SIOINT (8259) */
- 0, /* AACK! Shouldn't need this.....see sandpoint_pci.c for more info */
- 1, /* 17: EPIC IRQ 1: Active Low -- PCI Slot 1 */
- 1, /* 18: EPIC IRQ 2: Active Low -- PCI Slot 2 */
- 1, /* 19: EPIC IRQ 3: Active Low -- PCI Slot 3 */
- 1, /* 20: EPIC IRQ 4: Active Low -- PCI Slot 4 */
- 0, /* 21 -- Unused */
- 0, /* 22 -- Unused */
- 1, /* 23 -- IDE (Winbond INT C) */
- 1, /* 24 -- IDE (Winbond INT D) */
- /* 35 - 31 (EPIC 9 - 15) Unused */
-#else
- 1, /* 16: EPIC IRQ 0: Active Low -- PCI intrs */
- 1, /* 17: EPIC IRQ 1: Active Low -- PCI (possibly 8259) intrs */
- 1, /* 18: EPIC IRQ 2: Active Low -- PCI (possibly 8259) intrs */
- 1 /* 19: EPIC IRQ 3: Active Low -- PCI intrs */
- /* 20: EPIC IRQ 4: Not used */
-#endif
-};
-
-static void __init
-sandpoint_setup_arch(void)
-{
- loops_per_jiffy = 100000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#ifdef CONFIG_ROOT_NFS
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_HDA1;
-#endif
-
- /* Lookup PCI host bridges */
- sandpoint_find_bridges();
-
-#ifdef CONFIG_DUMMY_CONSOLE
- conswitchp = &dummy_con;
-#endif
-
- printk("Motorola SPS Sandpoint Test Platform\n");
- printk("Sandpoint port (MontaVista Software, Inc. (source@mvista.com))\n");
-
- /* The Sandpoint rom doesn't enable any caches. Do that now.
- * The 7450 portion will also set up the L3s once I get enough
- * information do do so. If the processor running doesn't have
- * and L2, the _set_L2CR is a no-op.
- */
- if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) {
- /* Just enable L2, the bits are different from others.
- */
- _set_L2CR(L2CR_L2E);
- }
- else {
- /* The magic number for Sandpoint/74xx PrPMCs.
- */
- _set_L2CR(0xbd014000);
- }
-}
-
-#define SANDPOINT_87308_CFG_ADDR 0x15c
-#define SANDPOINT_87308_CFG_DATA 0x15d
-
-#define SANDPOINT_87308_CFG_INB(addr, byte) { \
- outb((addr), SANDPOINT_87308_CFG_ADDR); \
- (byte) = inb(SANDPOINT_87308_CFG_DATA); \
-}
-
-#define SANDPOINT_87308_CFG_OUTB(addr, byte) { \
- outb((addr), SANDPOINT_87308_CFG_ADDR); \
- outb((byte), SANDPOINT_87308_CFG_DATA); \
-}
-
-#define SANDPOINT_87308_SELECT_DEV(dev_num) { \
- SANDPOINT_87308_CFG_OUTB(0x07, (dev_num)); \
-}
-
-#define SANDPOINT_87308_DEV_ENABLE(dev_num) { \
- SANDPOINT_87308_SELECT_DEV(dev_num); \
- SANDPOINT_87308_CFG_OUTB(0x30, 0x01); \
-}
-
-/*
- * Initialize the ISA devices on the Nat'l PC87308VUL SuperIO chip.
- */
-static void __init
-sandpoint_setup_natl_87308(void)
-{
- u_char reg;
-
- /*
- * Enable all the devices on the Super I/O chip.
- */
- SANDPOINT_87308_SELECT_DEV(0x00); /* Select kbd logical device */
- SANDPOINT_87308_CFG_OUTB(0xf0, 0x00); /* Set KBC clock to 8 Mhz */
- SANDPOINT_87308_DEV_ENABLE(0x00); /* Enable keyboard */
- SANDPOINT_87308_DEV_ENABLE(0x01); /* Enable mouse */
- SANDPOINT_87308_DEV_ENABLE(0x02); /* Enable rtc */
- SANDPOINT_87308_DEV_ENABLE(0x03); /* Enable fdc (floppy) */
- SANDPOINT_87308_DEV_ENABLE(0x04); /* Enable parallel */
- SANDPOINT_87308_DEV_ENABLE(0x05); /* Enable UART 2 */
- SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
- SANDPOINT_87308_DEV_ENABLE(0x06); /* Enable UART 1 */
- SANDPOINT_87308_CFG_OUTB(0xf0, 0x82); /* Enable bank select regs */
-
- /* Set up floppy in PS/2 mode */
- outb(0x09, SIO_CONFIG_RA);
- reg = inb(SIO_CONFIG_RD);
- reg = (reg & 0x3F) | 0x40;
- outb(reg, SIO_CONFIG_RD);
- outb(reg, SIO_CONFIG_RD); /* Have to write twice to change! */
-
- return;
-}
-
-/*
- * Fix IDE interrupts.
- */
-static void __init
-sandpoint_fix_winbond_83553(void)
-{
- /* Make all 8259 interrupt level sensitive */
- outb(0xf8, 0x4d0);
- outb(0xde, 0x4d1);
-
- return;
-}
-
-static void __init
-sandpoint_init2(void)
-{
- /* Do Sandpoint board specific initialization. */
- sandpoint_fix_winbond_83553();
- sandpoint_setup_natl_87308();
-
- request_region(0x00,0x20,"dma1");
- request_region(0x20,0x20,"pic1");
- request_region(0x40,0x20,"timer");
- request_region(0x80,0x10,"dma page reg");
- request_region(0xa0,0x20,"pic2");
- request_region(0xc0,0x20,"dma2");
-
- return;
-}
-
-/*
- * Interrupt setup and service. Interrrupts on the Sandpoint come
- * from the four PCI slots plus the 8259 in the Winbond Super I/O (SIO).
- * These interrupts are sent to one of four IRQs on the EPIC.
- * The SIO shares its interrupt with either slot 2 or slot 3 (INTA#).
- * Slot numbering is confusing. Sometimes in the documentation they
- * use 0,1,2,3 and others 1,2,3,4. We will use slots 1,2,3,4 and
- * map this to IRQ 16, 17, 18, 19.
- * For Sandpoint X3, this has been better designed. The 8259 is
- * cascaded from EPIC IRQ0, IRQ1-4 map to PCI slots 1-4, IDE is on
- * EPIC 7 and 8.
- */
-static void __init
-sandpoint_init_IRQ(void)
-{
- int i;
-
- /*
- * 3 things cause us to jump through some hoops:
- * 1) the EPIC on the 8240 & 107 are not full-blown openpic pic's
- * 2) the 8259 is NOT cascaded on the openpic IRQ 0
- * 3) the 8259 shares its interrupt line with some PCI interrupts.
- *
- * What we'll do is set up the 8259 to be level sensitive, active low
- * just like a PCI device. Then, when an interrupt on the IRQ that is
- * shared with the 8259 comes in, we'll take a peek at the 8259 to see
- * it its generating an interrupt. If it is, we'll handle the 8259
- * interrupt. Otherwise, we'll handle it just like a normal PCI
- * interrupt. This does give the 8259 interrupts a higher priority
- * than the EPIC ones--hopefully, not a problem.
- */
- OpenPIC_InitSenses = sandpoint_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof(sandpoint_openpic_initsenses);
-
- openpic_init(1, 0, NULL, -1);
-
- /*
- * openpic_init() has set up irq_desc[0-23] to be openpic
- * interrupts. We need to set irq_desc[0-15] to be 8259 interrupts.
- * We then need to request and enable the 8259 irq.
- */
- for(i=0; i < NUM_8259_INTERRUPTS; i++)
- irq_desc[i].handler = &i8259_pic;
-
- if (request_irq(SANDPOINT_SIO_IRQ, no_action, SA_INTERRUPT,
- "8259 cascade to EPIC", NULL)) {
-
- printk("Unable to get OpenPIC IRQ %d for cascade\n",
- SANDPOINT_SIO_IRQ);
- }
-
- i8259_init(NULL);
-}
-
-static int
-sandpoint_get_irq(struct pt_regs *regs)
-{
- int irq, cascade_irq;
-
- irq = openpic_irq();
-
- if (irq == SANDPOINT_SIO_IRQ) {
- cascade_irq = i8259_irq(regs);
-
- if (cascade_irq != -1) {
- irq = cascade_irq;
- openpic_eoi();
- }
- }
- else if (irq == OPENPIC_VEC_SPURIOUS) {
- irq = -1;
- }
-
- return irq;
-}
-
-static u32
-sandpoint_irq_canonicalize(u32 irq)
-{
- if (irq == 2)
- {
- return 9;
- }
- else
- {
- return irq;
- }
-}
-
-static ulong __init
-sandpoint_find_end_of_memory(void)
-{
- ulong size = 0;
-
-#if 0 /* Leave out until DINK sets mem ctlr correctly */
- size = mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-#else
- size = 32*1024*1024;
-#endif
-
- return size;
-}
-
-static void __init
-sandpoint_map_io(void)
-{
- io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-/*
- * Due to Sandpoint X2 errata, the Port 92 will not work.
- */
-static void
-sandpoint_restart(char *cmd)
-{
- local_irq_disable();
-
- /* Set exception prefix high - to the firmware */
- _nmask_and_or_msr(0, MSR_IP);
-
- /* Reset system via Port 92 */
- outb(0x00, 0x92);
- outb(0x01, 0x92);
- for(;;); /* Spin until reset happens */
-}
-
-static void
-sandpoint_power_off(void)
-{
- local_irq_disable();
- for(;;); /* No way to shut power off with software */
- /* NOTREACHED */
-}
-
-static void
-sandpoint_halt(void)
-{
- sandpoint_power_off();
- /* NOTREACHED */
-}
-
-static int
-sandpoint_show_cpuinfo(struct seq_file *m)
-{
- uint pvid;
-
- pvid = mfspr(PVR);
-
- seq_printf(m, "vendor\t\t: Motorola SPS\n");
- seq_printf(m, "machine\t\t: Sandpoint\n");
- seq_printf(m, "processor\t: PVID: 0x%x, vendor: %s\n",
- pvid, (pvid & (1<<15) ? "IBM" : "Motorola"));
-
- return 0;
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE support.
- */
-static int sandpoint_ide_ports_known = 0;
-static unsigned long sandpoint_ide_regbase[MAX_HWIFS];
-static unsigned long sandpoint_ide_ctl_regbase[MAX_HWIFS];
-static unsigned long sandpoint_idedma_regbase;
-
-static void
-sandpoint_ide_probe(void)
-{
- struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND,
- PCI_DEVICE_ID_WINBOND_82C105,
- NULL);
-
- if(pdev) {
- sandpoint_ide_regbase[0]=pdev->resource[0].start;
- sandpoint_ide_regbase[1]=pdev->resource[2].start;
- sandpoint_ide_ctl_regbase[0]=pdev->resource[1].start;
- sandpoint_ide_ctl_regbase[1]=pdev->resource[3].start;
- sandpoint_idedma_regbase=pdev->resource[4].start;
- }
-
- sandpoint_ide_ports_known = 1;
- return;
-}
-
-static int
-sandpoint_ide_default_irq(unsigned long base)
-{
- if (sandpoint_ide_ports_known == 0)
- sandpoint_ide_probe();
-
- if (base == sandpoint_ide_regbase[0])
- return SANDPOINT_IDE_INT0;
- else if (base == sandpoint_ide_regbase[1])
- return SANDPOINT_IDE_INT1;
- else
- return 0;
-}
-
-static unsigned long
-sandpoint_ide_default_io_base(int index)
-{
- if (sandpoint_ide_ports_known == 0)
- sandpoint_ide_probe();
-
- return sandpoint_ide_regbase[index];
-}
-
-static void __init
-sandpoint_ide_init_hwif_ports(hw_regs_t *hw, unsigned long data_port,
- unsigned long ctrl_port, int *irq)
-{
- unsigned long reg = data_port;
- uint alt_status_base;
- int i;
-
- for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
- hw->io_ports[i] = reg++;
- }
-
- if (data_port == sandpoint_ide_regbase[0]) {
- alt_status_base = sandpoint_ide_ctl_regbase[0] + 2;
- hw->irq = 14;
- }
- else if (data_port == sandpoint_ide_regbase[1]) {
- alt_status_base = sandpoint_ide_ctl_regbase[1] + 2;
- hw->irq = 15;
- }
- else {
- alt_status_base = 0;
- hw->irq = 0;
- }
-
- if (ctrl_port) {
- hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
- } else {
- hw->io_ports[IDE_CONTROL_OFFSET] = alt_status_base;
- }
-
- if (irq != NULL) {
- *irq = hw->irq;
- }
-
- return;
-}
-#endif
-
-/*
- * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1.
- */
-static __inline__ void
-sandpoint_set_bat(void)
-{
- unsigned long bat3u, bat3l;
- static int mapping_set = 0;
-
- if (!mapping_set) {
-
- __asm__ __volatile__(
- " lis %0,0xf800\n \
- ori %1,%0,0x002a\n \
- ori %0,%0,0x0ffe\n \
- mtspr 0x21e,%0\n \
- mtspr 0x21f,%1\n \
- isync\n \
- sync "
- : "=r" (bat3u), "=r" (bat3l));
-
- mapping_set = 1;
- }
-
- return;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
- SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */
-};
-
-static void
-sandpoint_progress(char *s, unsigned short hex)
-{
- volatile char c;
- volatile unsigned long com_port;
- u16 shift;
-
- com_port = rs_table[0].port;
- shift = rs_table[0].iomem_reg_shift;
-
- while ((c = *s++) != 0) {
- while ((*((volatile unsigned char *)com_port +
- (UART_LSR << shift)) & UART_LSR_THRE) == 0)
- ;
- *(volatile unsigned char *)com_port = c;
-
- if (c == '\n') {
- while ((*((volatile unsigned char *)com_port +
- (UART_LSR << shift)) & UART_LSR_THRE) == 0)
- ;
- *(volatile unsigned char *)com_port = '\r';
- }
- }
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
-__init void sandpoint_setup_pci_ptrs(void);
-
-TODC_ALLOC();
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- /* Map in board regs, etc. */
- sandpoint_set_bat();
-
- isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
- isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
- pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
- ISA_DMA_THRESHOLD = 0x00ffffff;
- DMA_MODE_READ = 0x44;
- DMA_MODE_WRITE = 0x48;
-
- ppc_md.setup_arch = sandpoint_setup_arch;
- ppc_md.show_cpuinfo = sandpoint_show_cpuinfo;
- ppc_md.irq_canonicalize = sandpoint_irq_canonicalize;
- ppc_md.init_IRQ = sandpoint_init_IRQ;
- ppc_md.get_irq = sandpoint_get_irq;
- ppc_md.init = sandpoint_init2;
-
- ppc_md.restart = sandpoint_restart;
- ppc_md.power_off = sandpoint_power_off;
- ppc_md.halt = sandpoint_halt;
-
- ppc_md.find_end_of_memory = sandpoint_find_end_of_memory;
- ppc_md.setup_io_mappings = sandpoint_map_io;
-
- TODC_INIT(TODC_TYPE_PC97307, 0x70, 0x00, 0x71, 8);
- ppc_md.time_init = todc_time_init;
- ppc_md.set_rtc_time = todc_set_rtc_time;
- ppc_md.get_rtc_time = todc_get_rtc_time;
- ppc_md.calibrate_decr = todc_calibrate_decr;
-
- ppc_md.nvram_read_val = todc_mc146818_read_val;
- ppc_md.nvram_write_val = todc_mc146818_write_val;
-
- ppc_md.heartbeat = NULL;
- ppc_md.heartbeat_reset = 0;
- ppc_md.heartbeat_count = 0;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = sandpoint_progress;
-#else /* !CONFIG_SERIAL_TEXT_DEBUG */
- ppc_md.progress = NULL;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
- ppc_ide_md.default_irq = sandpoint_ide_default_irq;
- ppc_ide_md.default_io_base = sandpoint_ide_default_io_base;
- ppc_ide_md.ide_init_hwif = sandpoint_ide_init_hwif_ports;
-#endif
-
- return;
-}
diff --git a/arch/ppc/platforms/zx4500.h b/arch/ppc/platforms/zx4500.h
deleted file mode 100644
index 8a26e691e940..000000000000
--- a/arch/ppc/platforms/zx4500.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* * arch/ppc/platforms/zx4500.h
- *
- * Board setup routines for Znyx ZX4500 cPCI board.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __PPC_PLATFORMS_ZX4500_H_
-#define __PPC_PLATFORMS_ZX4500_H_
-
-/*
- * Define the addresses of CPLD registers in CLPD area.
- */
-#define ZX4500_CPLD_BOARD_ID 0xff800001
-#define ZX4500_CPLD_REV 0xff800002
-#define ZX4500_CPLD_RESET 0xff800011
-#define ZX4500_CPLD_PHY1 0xff800014
-#define ZX4500_CPLD_PHY2 0xff800015
-#define ZX4500_CPLD_PHY3 0xff800016
-#define ZX4500_CPLD_SYSCTL 0xff800017
-#define ZX4500_CPLD_EXT_FLASH 0xff800018
-#define ZX4500_CPLD_DUAL1 0xff800019
-#define ZX4500_CPLD_DUAL2 0xff80001A
-#define ZX4500_CPLD_STATUS 0xff800030
-#define ZX4500_CPLD_STREAM 0xff800032
-#define ZX4500_CPLD_PHY1_LED 0xff800034
-#define ZX4500_CPLD_PHY2_LED 0xff800035
-#define ZX4500_CPLD_PHY3_LED 0xff800036
-#define ZX4500_CPLD_PHY1_LNK 0xff80003C
-#define ZX4500_CPLD_PHY2_LNK 0xff80003D
-#define ZX4500_CPLD_PHY3_LNK 0xff80003E
-
-#define ZX4500_CPLD_RESET_SOFT 0x01 /* Soft Reset */
-#define ZX4500_CPLD_RESET_XBUS 0x40 /* Reset entire board */
-
-#define ZX4500_CPLD_SYSCTL_PMC 0x01 /* Enable INTA/B/C/D from PMC */
-#define ZX4500_CPLD_SYSCTL_BCM 0x04 /* Enable INTA from BCM */
-#define ZX4500_CPLD_SYSCTL_SINTA 0x08 /* Enable SINTA from 21554 */
-#define ZX4500_CPLD_SYSCTL_WD 0x20 /* Enable Watchdog Timer */
-#define ZX4500_CPLD_SYSCTL_PMC_TRI 0x80 /* Tri-state PMC EREADY */
-
-#define ZX4500_CPLD_DUAL2_LED_PULL 0x01 /* Pull LED */
-#define ZX4500_CPLD_DUAL2_LED_EXT_FAULT 0x02 /* External Fault LED */
-#define ZX4500_CPLD_DUAL2_LED_INT_FAULT 0x04 /* Internal Fault LED */
-#define ZX4500_CPLD_DUAL2_LED_OK 0x08 /* OK LED */
-#define ZX4500_CPLD_DUAL2_LED_CLK 0x10 /* CLK LED */
-
-/*
- * Defines related to boot string stored in flash.
- */
-#define ZX4500_BOOT_STRING_ADDR 0xfff7f000
-#define ZX4500_BOOT_STRING_LEN 80
-
-/*
- * Define the IDSEL that the PCI bus side of the 8240 is connected to.
- * This IDSEL must not be selected from the 8240 processor side.
- */
-#define ZX4500_HOST_BRIDGE_IDSEL 20
-
-
-void zx4500_find_bridges(void);
-
-#endif /* __PPC_PLATFORMS_ZX4500_H_ */
diff --git a/arch/ppc/platforms/zx4500_pci.c b/arch/ppc/platforms/zx4500_pci.c
deleted file mode 100644
index 325ecfe31c93..000000000000
--- a/arch/ppc/platforms/zx4500_pci.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_pci.c
- *
- * PCI setup routines for Znyx ZX4500 cPCI boards.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-
-#include "zx4500.h"
-
-/*
- * Znyx ZX4500 interrupt routes.
- */
-static inline int
-zx4500_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
-{
- static char pci_irq_table[][4] =
- /*
- * PCI IDSEL/INTPIN->INTLINE
- * A B C D
- */
- {
- { 19, 0, 0, 0 }, /* IDSEL 21 - 21554 PCI-cPCI bridge */
- { 18, 0, 0, 0 }, /* IDSEL 22 - BCM5600 INTA */
- { 16, 20, 16, 20 }, /* IDSEL 23 - PPMC Slot */
- };
-
- const long min_idsel = 21, max_idsel = 23, irqs_per_slot = 4;
- return PCI_IRQ_TABLE_LOOKUP;
-}
-
-void __init
-zx4500_board_init(struct pci_controller *hose)
-{
- uint val;
- u_char sysctl;
-
- /*
- * CPLD Registers are mapped in by BAT 3 in zx4500_setup_arch().
- *
- * Turn off all interrupts routed through the CPLD.
- * Also, turn off watchdog timer and drive PMC EREADY low.
- */
- sysctl = in_8((volatile u_char *)ZX4500_CPLD_SYSCTL);
- sysctl &= ~(ZX4500_CPLD_SYSCTL_PMC |
- ZX4500_CPLD_SYSCTL_BCM |
- ZX4500_CPLD_SYSCTL_SINTA |
- ZX4500_CPLD_SYSCTL_WD |
- ZX4500_CPLD_SYSCTL_PMC_TRI);
- out_8((volatile u_char *)ZX4500_CPLD_SYSCTL, sysctl);
-
- /*
- * Kludge the size that BAR2 of the 21554 asks for
- * (i.e., set Upstream I/O or Memory 0 Setup Register).
- * Old versions of SROM wants 1 GB which is too large, make it ask
- * for 256 MB.
- */
- early_read_config_dword(hose, 0, PCI_DEVFN(21,0), 0xc4, &val);
-
- if (val != 0) {
- early_write_config_dword(hose,
- 0,
- PCI_DEVFN(21,0),
- 0xc4,
- val | 0xf0000000);
- }
-
- return;
-}
-
-static int
-zx4500_exclude_device(u_char bus, u_char devfn)
-{
- if ((bus == 0) && (PCI_SLOT(devfn) == ZX4500_HOST_BRIDGE_IDSEL)) {
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
- else {
- return PCIBIOS_SUCCESSFUL;
- }
-}
-
-void __init
-zx4500_find_bridges(void)
-{
- struct pci_controller *hose;
-
- hose = pcibios_alloc_controller();
-
- if (!hose)
- return;
-
- hose->first_busno = 0;
- hose->last_busno = 0xff;
-
- if (mpc10x_bridge_init(hose,
- MPC10X_MEM_MAP_B,
- MPC10X_MEM_MAP_B,
- MPC10X_MAPB_EUMB_BASE) == 0) {
-
- hose->mem_resources[0].end = 0xffffffff;
-
- /* Initialize the board */
- zx4500_board_init(hose);
-
- /* scan PCI bus */
- ppc_md.pci_exclude_device = zx4500_exclude_device;
- hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
-
- ppc_md.pcibios_fixup = NULL;
- ppc_md.pcibios_fixup_bus = NULL;
- ppc_md.pci_swizzle = common_swizzle;
- ppc_md.pci_map_irq = zx4500_map_irq;
- }
- else {
- if (ppc_md.progress)
- ppc_md.progress("Bridge init failed", 0x100);
- printk("Host bridge init failed\n");
- }
-
- return;
-}
diff --git a/arch/ppc/platforms/zx4500_serial.h b/arch/ppc/platforms/zx4500_serial.h
deleted file mode 100644
index e1f8c70337ba..000000000000
--- a/arch/ppc/platforms/zx4500_serial.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_serial.h
- *
- * Definitions for Znyx ZX4500 board support
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __ASMPPC_ZX4500_SERIAL_H
-#define __ASMPPC_ZX4500_SERIAL_H
-
-#include <linux/config.h>
-
-/* Define the UART base address (only 1 UART) */
-#define ZX4500_SERIAL_1 0xff880000
-
-#ifdef CONFIG_SERIAL_MANY_PORTS
-#define RS_TABLE_SIZE 64
-#else
-#define RS_TABLE_SIZE 1
-#endif
-
-/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
-#define BASE_BAUD ( 1843200 / 16 )
-
-#ifdef CONFIG_SERIAL_DETECT_IRQ
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
-#else
-#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
-#endif
-
-#define STD_SERIAL_PORT_DFNS \
- { 0, BASE_BAUD, ZX4500_SERIAL_1, 17, STD_COM_FLAGS, /* ttyS0 */ \
- iomem_base: (u8 *)ZX4500_SERIAL_1, \
- io_type: SERIAL_IO_MEM },
-
-#define SERIAL_PORT_DFNS \
- STD_SERIAL_PORT_DFNS
-
-#endif /* __ASMPPC_ZX4500_SERIAL_H */
diff --git a/arch/ppc/platforms/zx4500_setup.c b/arch/ppc/platforms/zx4500_setup.c
deleted file mode 100644
index 7a71b270956a..000000000000
--- a/arch/ppc/platforms/zx4500_setup.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * arch/ppc/platforms/zx4500_setup.c
- *
- * Board setup routines for Znyx ZX4500 family of cPCI boards.
- *
- * Author: Mark A. Greer
- * mgreer@mvista.com
- *
- * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-/*
- * This file adds support for the Znyx ZX4500 series of cPCI boards.
- * These boards have an 8240, UART on the processor bus, a PPMC slot (for now
- * the card in this slot can _not_ be a monarch), Broadcom BCM5600, and an
- * Intel 21554 bridge.
- *
- * Currently, this port assumes that the 8240 is the master and performs PCI
- * arbitration, etc. It is also assumed that the 8240 is wired to come up
- * using memory MAP B (CHRP map).
- *
- * Note: This board port will not work properly as it is. You must apply the
- * patch that is at ftp://ftp.mvista.com/pub/Area51/zx4500/zx_patch_2_5
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/initrd.h>
-#include <linux/console.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <linux/root_dev.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/prom.h>
-#include <asm/time.h>
-#include <asm/open_pic.h>
-#include <asm/mpc10x.h>
-#include <asm/pci-bridge.h>
-#include <asm/bootinfo.h>
-
-#include "zx4500.h"
-
-static u_char zx4500_openpic_initsenses[] __initdata = {
- 0, /* 0-15 are not used on an 8240 EPIC */
- 0, /* 1 */
- 0, /* 2 */
- 0, /* 3 */
- 0, /* 4 */
- 0, /* 5 */
- 0, /* 6 */
- 0, /* 7 */
- 0, /* 8 */
- 0, /* 9 */
- 0, /* 10 */
- 0, /* 11 */
- 0, /* 12 */
- 0, /* 13 */
- 0, /* 14 */
- 0, /* 15 */
- 1, /* 16: EPIC IRQ 0: Active Low -- PMC #INTA & #INTC */
- 1, /* 17: EPIC IRQ 1: Active Low -- UART */
- 1, /* 18: EPIC IRQ 2: Active Low -- BCM5600 #INTA */
- 1, /* 19: EPIC IRQ 3: Active Low -- 21554 #SINTA */
- 1, /* 20: EPIC IRQ 4: Active Low -- PMC #INTB & #INTD */
-};
-
-
-static void __init
-zx4500_setup_arch(void)
-{
- char boot_string[ZX4500_BOOT_STRING_LEN + 1];
- char *boot_arg;
- extern char cmd_line[];
-
-
- loops_per_jiffy = 50000000 / HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- ROOT_DEV = Root_RAM0;
- else
-#endif
-#if defined(CONFIG_ROOT_NFS)
- ROOT_DEV = Root_NFS;
-#else
- ROOT_DEV = Root_SDA1;
-#endif
-
- /* Get boot string from flash */
- strlcpy(boot_string,
- (char *)ZX4500_BOOT_STRING_ADDR,
- sizeof(boot_string));
- boot_string[ZX4500_BOOT_STRING_LEN] = '\0';
-
- /* Can be delimited by 0xff */
- boot_arg = strchr(boot_string, 0xff);
-
- if (boot_arg != NULL) {
- *boot_arg = '\0';
- }
-
- /* First 3 chars must be 'dev'. If not, ignore. */
- if (!strncmp(boot_string, "dev", 3)) {
- /* skip 'dev?' and any blanks after it */
- boot_arg = strchr(boot_string, ' ');
-
- if (boot_arg != NULL) {
- while (*boot_arg == ' ') boot_arg++;
- strcat(cmd_line, " ");
- strcat(cmd_line, boot_arg);
- }
- }
-
- /* nothing but serial consoles... */
- printk("Znyx ZX4500 Series High Performance Switch\n");
- printk("ZX4500 port (C) 2000, 2001 MontaVista Software, Inc. (source@mvista.com)\n");
-
- /* Lookup PCI host bridge */
- zx4500_find_bridges();
-
- printk("ZX4500 Board ID: 0x%x, Revision #: 0x%x\n",
- in_8((volatile u_char *)ZX4500_CPLD_BOARD_ID),
- in_8((volatile u_char *)ZX4500_CPLD_REV));
-
- return;
-}
-
-static ulong __init
-zx4500_find_end_of_memory(void)
-{
- return mpc10x_get_mem_size(MPC10X_MEM_MAP_B);
-}
-
-static void __init
-zx4500_map_io(void)
-{
- io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
-}
-
-/*
- * Enable interrupts routed thru CPLD to reach the 8240's EPIC.
- * Need to enable all 4 PMC intrs, BCM INTA, and 21554 SINTA to 8240.
- * UART intrs routed directly to 8240 (not thru CPLD).
- */
-static void __init
-zx4500_enable_cpld_intrs(void)
-{
- u_char sysctl;
-
- sysctl = in_8((volatile u_char *)ZX4500_CPLD_SYSCTL);
- sysctl |= (ZX4500_CPLD_SYSCTL_PMC |
- ZX4500_CPLD_SYSCTL_BCM |
- ZX4500_CPLD_SYSCTL_SINTA);
- out_8((volatile u_char *)ZX4500_CPLD_SYSCTL, sysctl);
-
- return;
-}
-
-static void __init
-zx4500_init_IRQ(void)
-{
- OpenPIC_InitSenses = zx4500_openpic_initsenses;
- OpenPIC_NumInitSenses = sizeof(zx4500_openpic_initsenses);
-
- openpic_init(1, 0, NULL, -1);
-
- zx4500_enable_cpld_intrs(); /* Allow CPLD to route intrs to 8240 */
-
- return;
-}
-
-static void
-zx4500_restart(char *cmd)
-{
- local_irq_disable();
-
- out_8((volatile u_char *)ZX4500_CPLD_RESET, ZX4500_CPLD_RESET_XBUS);
- for (;;);
-
- panic("Restart failed.\n");
- /* NOTREACHED */
-}
-
-static void
-zx4500_power_off(void)
-{
- local_irq_disable();
- for(;;); /* No way to shut power off with software */
- /* NOTREACHED */
-}
-
-static void
-zx4500_halt(void)
-{
- zx4500_power_off();
- /* NOTREACHED */
-}
-
-static int
-zx4500_get_bus_speed(void)
-{
- int bus_speed;
-
- bus_speed = 100000000;
-
- return bus_speed;
-}
-
-static int
-zx4500_show_cpuinfo(struct seq_file *m)
-{
- uint pvid;
-
- seq_printf(m, "vendor\t\t: Znyx\n");
- seq_printf(m, "machine\t\t: ZX4500\n");
- seq_printf(m, "processor\t: PVID: 0x%x, vendor: %s\n",
- pvid, (pvid & (1<<15) ? "IBM" : "Motorola"));
- seq_printf(m, "bus speed\t: %dMhz\n",
- zx4500_get_bus_speed()/1000000);
-
- return 0;
-}
-
-static void __init
-zx4500_calibrate_decr(void)
-{
- ulong freq;
-
- freq = zx4500_get_bus_speed() / 4;
-
- printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
- freq/1000000, freq%1000000);
-
- tb_ticks_per_jiffy = freq / HZ;
- tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
- return;
-}
-
-/*
- * Set BAT 3 to map 0xf0000000 to end of physical memory space 1-1.
- */
-static __inline__ void
-zx4500_set_bat(void)
-{
- unsigned long bat3u, bat3l;
- static int mapping_set = 0;
-
- if (!mapping_set) {
-
- __asm__ __volatile__(
- " lis %0,0xf800\n \
- ori %1,%0,0x002a\n \
- ori %0,%0,0x0ffe\n \
- mtspr 0x21e,%0\n \
- mtspr 0x21f,%1\n \
- isync\n \
- sync "
- : "=r" (bat3u), "=r" (bat3l));
-
- mapping_set = 1;
- }
-
- return;
-}
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-#include <asm/serial.h>
-
-static struct serial_state rs_table[RS_TABLE_SIZE] = {
- SERIAL_PORT_DFNS /* Defined in <asm/serial.h> */
-};
-
-void
-zx4500_progress(char *s, unsigned short hex)
-{
- volatile char c;
- volatile unsigned long com_port;
- u16 shift;
-
- com_port = rs_table[0].port;
- shift = rs_table[0].iomem_reg_shift;
-
- while ((c = *s++) != 0) {
- while ((*((volatile unsigned char *)com_port +
- (UART_LSR << shift)) & UART_LSR_THRE) == 0)
- ;
- *(volatile unsigned char *)com_port = c;
-
- if (c == '\n') {
- while ((*((volatile unsigned char *)com_port +
- (UART_LSR << shift)) & UART_LSR_THRE) == 0)
- ;
- *(volatile unsigned char *)com_port = '\r';
- }
- }
-}
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
- unsigned long r6, unsigned long r7)
-{
- parse_bootinfo(find_bootinfo());
-
- /* Map in board registers, etc. */
- zx4500_set_bat();
-
- isa_io_base = MPC10X_MAPB_ISA_IO_BASE;
- isa_mem_base = MPC10X_MAPB_ISA_MEM_BASE;
- pci_dram_offset = MPC10X_MAPB_DRAM_OFFSET;
-
- ppc_md.setup_arch = zx4500_setup_arch;
- ppc_md.show_cpuinfo = zx4500_show_cpuinfo;
- ppc_md.irq_canonicalize = NULL;
- ppc_md.init_IRQ = zx4500_init_IRQ;
- ppc_md.get_irq = openpic_get_irq;
- ppc_md.init = NULL;
-
- ppc_md.restart = zx4500_restart;
- ppc_md.power_off = zx4500_power_off;
- ppc_md.halt = zx4500_halt;
-
- ppc_md.find_end_of_memory = zx4500_find_end_of_memory;
- ppc_md.setup_io_mappings = zx4500_map_io;
-
- ppc_md.calibrate_decr = zx4500_calibrate_decr;
-
- ppc_md.heartbeat = NULL;
- ppc_md.heartbeat_reset = 0;
- ppc_md.heartbeat_count = 0;
-
-#ifdef CONFIG_SERIAL_TEXT_DEBUG
- ppc_md.progress = zx4500_progress;
-#else /* !CONFIG_SERIAL_TEXT_DEBUG */
- ppc_md.progress = NULL;
-#endif /* CONFIG_SERIAL_TEXT_DEBUG */
-
- return;
-}
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 62bb56c8e6ce..9fd63b6030a9 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -61,8 +61,9 @@ obj-$(CONFIG_SANDPOINT) += i8259.o open_pic.o mpc10x_common.o \
pci_auto.o indirect_pci.o todc_time.o
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
todc_time.o
-obj-$(CONFIG_ZX4500) += indirect_pci.o pci_auto.o mpc10x_common.o \
- i8259.o open_pic.o
obj-$(CONFIG_8260) += m8260_setup.o ppc8260_pic.o
+ifeq ($(CONFIG_SERIAL_8250)$(CONFIG_PPC_GEN550),yy)
+obj-$(CONFIG_KGDB) += gen550_kgdb.o gen550_dbg.o
+obj-$(CONFIG_SERIAL_TEXT_DEBUG) += gen550_dbg.o
+endif
obj-$(CONFIG_BOOTX_TEXT) += btext.o
-
diff --git a/arch/ppc/syslib/gen550_dbg.c b/arch/ppc/syslib/gen550_dbg.c
new file mode 100644
index 000000000000..7fb0b41a241c
--- /dev/null
+++ b/arch/ppc/syslib/gen550_dbg.c
@@ -0,0 +1,174 @@
+/*
+ * arch/ppc/syslib/gen550_dbg.c
+ *
+ * A library of polled 16550 serial routines. These are intended to
+ * be used to support progress messages, xmon, kgdb, etc. on a
+ * variety of platforms.
+ *
+ * Adapted from lots of code ripped from the arch/ppc/boot/ polled
+ * 16550 support.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2002-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/tty.h> /* For linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+#include <asm/machdep.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+#define SERIAL_BAUD 9600
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+ SERIAL_PORT_DFNS /* defined in <asm/serial.h> */
+};
+
+static void (*serial_outb)(unsigned long, unsigned char);
+static unsigned long (*serial_inb)(unsigned long);
+
+static int shift;
+
+unsigned long direct_inb(unsigned long addr)
+{
+ return readb(addr);
+}
+
+void direct_outb(unsigned long addr, unsigned char val)
+{
+ writeb(val, addr);
+}
+
+unsigned long io_inb(unsigned long port)
+{
+ return inb(port);
+}
+
+void io_outb(unsigned long port, unsigned char val)
+{
+ outb(val, port);
+}
+
+unsigned long serial_init(int chan, void *ignored)
+{
+ unsigned long com_port;
+ unsigned char lcr, dlm;
+
+ /* We need to find out which type io we're expecting. If it's
+ * 'SERIAL_IO_PORT', we get an offset from the isa_io_base.
+ * If it's 'SERIAL_IO_MEM', we can the exact location. -- Tom */
+ switch (rs_table[chan].io_type) {
+ case SERIAL_IO_PORT:
+ com_port = rs_table[chan].port;
+ serial_outb = io_outb;
+ serial_inb = io_inb;
+ break;
+ case SERIAL_IO_MEM:
+ com_port = (unsigned long)rs_table[chan].iomem_base;
+ serial_outb = direct_outb;
+ serial_inb = direct_inb;
+ break;
+ default:
+ /* We can't deal with it. */
+ return -1;
+ }
+
+ /* How far apart the registers are. */
+ shift = rs_table[chan].iomem_reg_shift;
+
+ /* save the LCR */
+ lcr = serial_inb(com_port + (UART_LCR << shift));
+
+ /* Access baud rate */
+ serial_outb(com_port + (UART_LCR << shift), UART_LCR_DLAB);
+ dlm = serial_inb(com_port + (UART_DLM << shift));
+
+ /*
+ * Test if serial port is unconfigured
+ * We assume that no-one uses less than 110 baud or
+ * less than 7 bits per character these days.
+ * -- paulus.
+ */
+ if ((dlm <= 4) && (lcr & 2)) {
+ /* port is configured, put the old LCR back */
+ serial_outb(com_port + (UART_LCR << shift), lcr);
+ }
+ else {
+ /* Input clock. */
+ serial_outb(com_port + (UART_DLL << shift),
+ (rs_table[chan].baud_base / SERIAL_BAUD) & 0xFF);
+ serial_outb(com_port + (UART_DLM << shift),
+ (rs_table[chan].baud_base / SERIAL_BAUD) >> 8);
+ /* 8 data, 1 stop, no parity */
+ serial_outb(com_port + (UART_LCR << shift), 0x03);
+ /* RTS/DTR */
+ serial_outb(com_port + (UART_MCR << shift), 0x03);
+
+ /* Clear & enable FIFOs */
+ serial_outb(com_port + (UART_FCR << shift), 0x07);
+ }
+
+ return (com_port);
+}
+
+void
+serial_putc(unsigned long com_port, unsigned char c)
+{
+ while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_THRE) == 0)
+ ;
+ serial_outb(com_port, c);
+}
+
+unsigned char
+serial_getc(unsigned long com_port)
+{
+ while ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) == 0)
+ ;
+ return serial_inb(com_port);
+}
+
+int
+serial_tstc(unsigned long com_port)
+{
+ return ((serial_inb(com_port + (UART_LSR << shift)) & UART_LSR_DR) != 0);
+}
+
+void
+serial_close(unsigned long com_port)
+{
+}
+
+void
+gen550_init(int i, struct uart_port *serial_req)
+{
+ rs_table[i].io_type = serial_req->iotype;
+ rs_table[i].port = serial_req->line;
+ rs_table[i].iomem_base = serial_req->membase;
+ rs_table[i].iomem_reg_shift = serial_req->regshift;
+}
+
+#ifdef CONFIG_SERIAL_TEXT_DEBUG
+void
+gen550_progress(char *s, unsigned short hex)
+{
+ volatile unsigned int progress_debugport;
+ volatile char c;
+
+ progress_debugport = serial_init(0, NULL);
+
+ serial_putc(progress_debugport, '\r');
+
+ while ((c = *s++) != 0)
+ serial_putc(progress_debugport, c);
+
+ serial_putc(progress_debugport, '\n');
+ serial_putc(progress_debugport, '\r');
+}
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
diff --git a/arch/ppc/syslib/gen550_kgdb.c b/arch/ppc/syslib/gen550_kgdb.c
new file mode 100644
index 000000000000..93b374f25dc3
--- /dev/null
+++ b/arch/ppc/syslib/gen550_kgdb.c
@@ -0,0 +1,84 @@
+/*
+ * arch/ppc/syslib/gen550_kgdb.c
+ *
+ * Generic 16550 kgdb support intended to be useful on a variety
+ * of platforms. To enable this support, it is necessary to set
+ * the CONFIG_GEN550 option. Any virtual mapping of the serial
+ * port(s) to be used can be accomplished by setting
+ * ppc_md.early_serial_map to a platform-specific mapping function.
+ *
+ * Adapted from ppc4xx_kgdb.c.
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *
+ * 2002-2003 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+#include <asm/machdep.h>
+
+extern unsigned long serial_init(int, void *);
+extern unsigned long serial_getc(unsigned long);
+extern unsigned long serial_putc(unsigned long, unsigned char);
+
+#if defined(CONFIG_KGDB_TTYS0)
+#define KGDB_PORT 0
+#elif defined(CONFIG_KGDB_TTYS1)
+#define KGDB_PORT 1
+#elif defined(CONFIG_KGDB_TTYS2)
+#define KGDB_PORT 2
+#elif defined(CONFIG_KGDB_TTYS3)
+#define KGDB_PORT 3
+#else
+#error "invalid kgdb_tty port"
+#endif
+
+static volatile unsigned int kgdb_debugport;
+
+void putDebugChar(unsigned char c)
+{
+ if (kgdb_debugport == 0)
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+ serial_putc(kgdb_debugport, c);
+}
+
+int getDebugChar(void)
+{
+ if (kgdb_debugport == 0)
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+
+ return(serial_getc(kgdb_debugport));
+}
+
+void kgdb_interruptible(int enable)
+{
+ return;
+}
+
+void putDebugString(char* str)
+{
+ while (*str != '\0') {
+ putDebugChar(*str);
+ str++;
+ }
+ putDebugChar('\r');
+ return;
+}
+
+/*
+ * Note: gen550_init() must be called already on the port we are going
+ * to use.
+ */
+void
+kgdb_map_scc(void)
+{
+ printk(KERN_DEBUG "kgdb init\n");
+ kgdb_debugport = serial_init(KGDB_PORT, NULL);
+}
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 9c292607e4ad..dbbc9d6ecd00 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -33,6 +33,7 @@
void* OpenPIC_Addr;
static volatile struct OpenPIC *OpenPIC = NULL;
+
/*
* We define OpenPIC_InitSenses table thusly:
* bit 0x1: sense, 0 for edge and 1 for level.
@@ -261,32 +262,32 @@ static void openpic_safe_writefield_IPI(volatile u_int *addr, u_int mask, u_int
}
#endif /* CONFIG_SMP */
-#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PMAC_PBOOK)
-static void openpic_reset(void)
+#ifdef CONFIG_EPIC_SERIAL_MODE
+static void __init openpic_eicr_set_clk(u_int clkval)
{
- openpic_setfield(&OpenPIC->Global.Global_Configuration0,
- OPENPIC_CONFIG_RESET);
- while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
- OPENPIC_CONFIG_RESET))
- mb();
+ openpic_writefield(&OpenPIC->Global.Global_Configuration1,
+ OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
}
-#endif
-#ifdef CONFIG_EPIC_SERIAL_MODE
-static void openpic_enable_sie(void)
+static void __init openpic_enable_sie(void)
{
openpic_setfield(&OpenPIC->Global.Global_Configuration1,
- OPENPIC_EICR_SIE);
+ OPENPIC_EICR_SIE);
}
+#endif
-static void openpic_eicr_set_clk(u_int clkval)
+#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PMAC_PBOOK)
+static void openpic_reset(void)
{
- openpic_writefield(&OpenPIC->Global.Global_Configuration1,
- OPENPIC_EICR_S_CLK_MASK, (clkval << 28));
+ openpic_setfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET);
+ while (openpic_readfield(&OpenPIC->Global.Global_Configuration0,
+ OPENPIC_CONFIG_RESET))
+ mb();
}
#endif
-void openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
+void __init openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
{
volatile OpenPIC_Source *src = first_ISR;
int i, last_irq;
@@ -300,7 +301,14 @@ void openpic_set_sources(int first_irq, int num_irqs, void *first_ISR)
ISR[i] = src;
}
-void __init openpic_init(int linux_irq_offset)
+/*
+ * The `offset' parameter defines where the interrupts handled by the
+ * OpenPIC start in the space of interrupt numbers that the kernel knows
+ * about. In other words, the OpenPIC's IRQ0 is numbered `offset' in the
+ * kernel's interrupt numbering scheme.
+ * We assume there is only one OpenPIC.
+ */
+void __init openpic_init(int offset)
{
u_int t, i;
u_int timerfreq;
@@ -349,13 +357,13 @@ void __init openpic_init(int linux_irq_offset)
printk("OpenPIC timer frequency is %d.%06d MHz\n",
timerfreq / 1000000, timerfreq % 1000000);
- open_pic_irq_offset = linux_irq_offset;
+ open_pic_irq_offset = offset;
/* Initialize timer interrupts */
if ( ppc_md.progress ) ppc_md.progress("openpic: timer",0x3ba);
for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
/* Disabled, Priority 0 */
- openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+linux_irq_offset);
+ openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i+offset);
/* No processor */
openpic_maptimer(i, 0);
}
@@ -365,12 +373,10 @@ void __init openpic_init(int linux_irq_offset)
if ( ppc_md.progress ) ppc_md.progress("openpic: ipi",0x3bb);
for (i = 0; i < OPENPIC_NUM_IPI; i++) {
/* Disabled, Priority 10..13 */
- openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+linux_irq_offset);
+ openpic_initipi(i, 10+i, OPENPIC_VEC_IPI+i+offset);
/* IPIs are per-CPU */
- irq_desc[OPENPIC_VEC_IPI+i+linux_irq_offset].status |=
- IRQ_PER_CPU;
- irq_desc[OPENPIC_VEC_IPI+i+linux_irq_offset].handler =
- &open_pic_ipi;
+ irq_desc[OPENPIC_VEC_IPI+i+offset].status |= IRQ_PER_CPU;
+ irq_desc[OPENPIC_VEC_IPI+i+offset].handler = &open_pic_ipi;
}
#endif
@@ -387,40 +393,36 @@ void __init openpic_init(int linux_irq_offset)
continue;
/* the bootloader may have left it enabled (bad !) */
- openpic_disable_irq(i+linux_irq_offset);
+ openpic_disable_irq(i+offset);
- /*
- * We find the value from either the InitSenses table
- * or assume a negative polarity level interrupt.
- */
- sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: 1;
+ sense = (i < OpenPIC_NumInitSenses)? OpenPIC_InitSenses[i]: \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
- if ((sense & IRQ_SENSE_MASK) == 1)
- irq_desc[i+linux_irq_offset].status = IRQ_LEVEL;
+ if (sense & IRQ_SENSE_MASK)
+ irq_desc[i+offset].status = IRQ_LEVEL;
/* Enabled, Priority 8 */
- openpic_initirq(i, 8, i + linux_irq_offset,
- (sense & IRQ_POLARITY_MASK),
+ openpic_initirq(i, 8, i+offset, (sense & IRQ_POLARITY_MASK),
(sense & IRQ_SENSE_MASK));
/* Processor 0 */
openpic_mapirq(i, 1<<0, 0);
}
/* Init descriptors */
- for (i = linux_irq_offset; i < NumSources + linux_irq_offset; i++)
+ for (i = offset; i < NumSources + offset; i++)
irq_desc[i].handler = &open_pic;
/* Initialize the spurious interrupt */
if (ppc_md.progress) ppc_md.progress("openpic: spurious",0x3bd);
- openpic_set_spurious(OPENPIC_VEC_SPURIOUS+linux_irq_offset);
+ openpic_set_spurious(OPENPIC_VEC_SPURIOUS+offset);
/* Initialize the cascade */
- if (linux_irq_offset) {
- if (request_irq(linux_irq_offset, no_action, SA_INTERRUPT,
+ if (offset) {
+ if (request_irq(offset, no_action, SA_INTERRUPT,
"82c59 cascade", NULL))
printk("Unable to get OpenPIC IRQ 0 for cascade\n");
}
- openpic_disable_8259_pass_through();
+ openpic_disable_8259_pass_through();
#ifdef CONFIG_EPIC_SERIAL_MODE
openpic_eicr_set_clk(7); /* Slowest value until we know better */
openpic_enable_sie();
@@ -479,7 +481,7 @@ static u_int openpic_get_priority(void)
}
#endif /* notused */
-static void openpic_set_priority(u_int pri)
+static void __init openpic_set_priority(u_int pri)
{
DECL_THIS_CPU;
@@ -656,29 +658,18 @@ static void __init openpic_maptimer(u_int timer, u_int cpumask)
}
/*
- * Initalize the interrupt source which will generate an NMI (and disable it).
+ * Initalize the interrupt source which will generate an NMI.
+ * This raises the interrupt's priority from 8 to 9.
*
* irq: The logical IRQ which generates an NMI.
*/
void __init
openpic_init_nmi_irq(u_int irq)
{
- int sense;
-
- /* If this wasn't given, assume a level, negative polarity interrupt. */
- sense = (irq < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[irq] :
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE);
-
- openpic_safe_writefield(&ISR[irq]->Vector_Priority,
- OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
- OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK,
- (9 << OPENPIC_PRIORITY_SHIFT) |
- (irq + open_pic_irq_offset) |
- ((sense & IRQ_POLARITY_MASK) ?
- OPENPIC_POLARITY_POSITIVE :
- OPENPIC_POLARITY_NEGATIVE) |
- ((sense & IRQ_SENSE_MASK) ? OPENPIC_SENSE_LEVEL
- : OPENPIC_SENSE_EDGE));
+ check_arg_irq(irq);
+ openpic_safe_writefield(&ISR[irq - open_pic_irq_offset]->Vector_Priority,
+ OPENPIC_PRIORITY_MASK,
+ 9 << OPENPIC_PRIORITY_SHIFT);
}
/*
@@ -752,7 +743,8 @@ void openpic_disable_ipi(u_int irq)
* pol: polarity (1 for positive, 0 for negative)
* sense: 1 for level, 0 for edge
*/
-static void openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
+static void __init
+openpic_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense)
{
openpic_safe_writefield(&ISR[irq]->Vector_Priority,
OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 79b716dbe6db..ca2472a9116a 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -109,7 +109,7 @@ void show_mem(void)
show_free_areas();
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
- for (i = 0; i < pgdat->node_size; i++) {
+ for (i = 0; i < pgdat->node_spanned_pages; i++) {
page = pgdat->node_mem_map + i;
total++;
if (PageReserved(page))
@@ -564,7 +564,7 @@ void __init mem_init(void)
int nid;
for (nid = 0; nid < numnodes; nid++) {
- if (node_data[nid].node_size != 0) {
+ if (node_data[nid].node_spanned_pages != 0) {
printk("freeing bootmem node %x\n", nid);
totalram_pages +=
free_all_bootmem_node(NODE_DATA(nid));
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index fd86d7ec8267..19b4ee36ee8f 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -160,21 +160,21 @@ new_range:
* this simple case and complain if there is a gap in
* memory
*/
- if (node_data[numa_domain].node_size) {
+ if (node_data[numa_domain].node_spanned_pages) {
unsigned long shouldstart =
node_data[numa_domain].node_start_pfn +
- node_data[numa_domain].node_size;
+ node_data[numa_domain].node_spanned_pages;
if (shouldstart != (start / PAGE_SIZE)) {
printk(KERN_ERR "Hole in node, disabling "
"region start %lx length %lx\n",
start, size);
continue;
}
- node_data[numa_domain].node_size += size / PAGE_SIZE;
+ node_data[numa_domain].node_spanned_pages += size / PAGE_SIZE;
} else {
node_data[numa_domain].node_start_pfn =
start / PAGE_SIZE;
- node_data[numa_domain].node_size = size / PAGE_SIZE;
+ node_data[numa_domain].node_spanned_pages = size / PAGE_SIZE;
}
for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
@@ -202,7 +202,7 @@ void setup_nonnuma(void)
map_cpu_to_node(i, 0);
node_data[0].node_start_pfn = 0;
- node_data[0].node_size = lmb_end_of_DRAM() / PAGE_SIZE;
+ node_data[0].node_spanned_pages = lmb_end_of_DRAM() / PAGE_SIZE;
for (i = 0 ; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
@@ -224,12 +224,12 @@ void __init do_init_bootmem(void)
unsigned long bootmem_paddr;
unsigned long bootmap_pages;
- if (node_data[nid].node_size == 0)
+ if (node_data[nid].node_spanned_pages == 0)
continue;
start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE;
end_paddr = start_paddr +
- (node_data[nid].node_size * PAGE_SIZE);
+ (node_data[nid].node_spanned_pages * PAGE_SIZE);
dbg("node %d\n", nid);
dbg("start_paddr = %lx\n", start_paddr);
@@ -311,7 +311,7 @@ void __init paging_init(void)
unsigned long start_pfn;
unsigned long end_pfn;
- if (node_data[nid].node_size == 0)
+ if (node_data[nid].node_spanned_pages == 0)
continue;
start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT;
diff --git a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c
index 74245a64e514..33832846833f 100644
--- a/arch/s390/kernel/compat_exec.c
+++ b/arch/s390/kernel/compat_exec.c
@@ -23,6 +23,7 @@
#include <linux/spinlock.h>
#include <linux/binfmts.h>
#include <linux/module.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -55,7 +56,7 @@ int setup_arg_pages32(struct linux_binprm *bprm)
if (!mpnt)
return -ENOMEM;
- if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+ if (security_vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
kmem_cache_free(vm_area_cachep, mpnt);
return -ENOMEM;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 1c43b3d40787..a4f84f8c6bcc 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -107,7 +107,7 @@ void __devinit cpu_init (void)
current->active_mm = &init_mm;
if (current->mm)
BUG();
- enter_lazy_tlb(&init_mm, current, nr);
+ enter_lazy_tlb(&init_mm, current);
}
/*
diff --git a/arch/sh/kernel/cpu/sh4/pci-sh7751.c b/arch/sh/kernel/cpu/sh4/pci-sh7751.c
index 365c71a4fbe0..0831b1c646ac 100644
--- a/arch/sh/kernel/cpu/sh4/pci-sh7751.c
+++ b/arch/sh/kernel/cpu/sh4/pci-sh7751.c
@@ -200,7 +200,7 @@ static void __init pcibios_fixup_peer_bridges(void)
return;
PCIDBG(2,"PCI: Peer bridge fixup\n");
for (n=0; n <= pcibios_last_bus; n++) {
- if (pci_bus_exists(&pci_root_buses, n))
+ if (pci_find_bus(0, n))
continue;
bus.number = n;
bus.ops = pci_root_ops;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 5764acac8480..8ee1cc052721 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -924,6 +924,13 @@ config DEBUG_SPINLOCK
best used in conjunction with the NMI watchdog so that spinlock
deadlocks are also debuggable.
+config KALLSYMS
+ bool "Load all symbols for debugging/ksymoops"
+ help
+ Say Y here to let the kernel print out symbolic crash information and
+ symbolic stack backtraces. This increases the size of the kernel
+ somewhat, as all symbols have to be loaded into the kernel image.
+
config DEBUG_SPINLOCK_SLEEP
bool "Sleep-inside-spinlock checking"
help
diff --git a/arch/sparc64/boot/Makefile b/arch/sparc64/boot/Makefile
index 0e46fc2d9821..5eb14ff1c518 100644
--- a/arch/sparc64/boot/Makefile
+++ b/arch/sparc64/boot/Makefile
@@ -10,11 +10,11 @@ ELFTOAOUT := elftoaout
host-progs := piggyback
targets := image tftpboot.img vmlinux.aout
-quiet_cmd_elftoaout = ELT2AOUT $@
+quiet_cmd_elftoaout = ELF2AOUT $@
cmd_elftoaout = $(ELFTOAOUT) vmlinux -o $@
-quiet_cmd_piggy = PIGGY $@
+quiet_cmd_piggy = PIGGY $@
cmd_piggy = $(obj)/piggyback $@ System.map $(ROOT_IMG)
-quiet_cmd_strip = STRIP $@
+quiet_cmd_strip = STRIP $@
cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 7902b35f01d1..c606b4721b59 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -733,7 +733,7 @@ void handler_irq(int irq, struct pt_regs *regs)
#endif
irq_enter();
- kstat_cpu(cpu).irqs[irq]++;
+ kstat_this_cpu.irqs[irq]++;
/* Sliiiick... */
#ifndef CONFIG_SMP
@@ -805,7 +805,7 @@ void sparc_floppy_irq(int irq, void *dev_cookie, struct pt_regs *regs)
int cpu = smp_processor_id();
irq_enter();
- kstat_cpu(cpu).irqs[irq]++;
+ kstat_this_cpu.irqs[irq]++;
*(irq_work(cpu, irq)) = 0;
bucket = get_ino_in_irqaction(action) + ivector_table;
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c
index 6326ab3761ea..46d473c10417 100644
--- a/arch/sparc64/kernel/process.c
+++ b/arch/sparc64/kernel/process.c
@@ -16,6 +16,7 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
+#include <linux/kallsyms.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
@@ -284,6 +285,7 @@ void __show_regs(struct pt_regs * regs)
#endif
printk("TSTATE: %016lx TPC: %016lx TNPC: %016lx Y: %08x %s\n", regs->tstate,
regs->tpc, regs->tnpc, regs->y, print_tainted());
+ print_symbol("TPC: <%s>\n", regs->tpc);
printk("g0: %016lx g1: %016lx g2: %016lx g3: %016lx\n",
regs->u_regs[0], regs->u_regs[1], regs->u_regs[2],
regs->u_regs[3]);
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index a5504b899178..0d0ff4e20428 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -1060,7 +1060,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
irq_enter();
if (cpu == boot_cpu_id) {
- kstat_cpu(cpu).irqs[0]++;
+ kstat_this_cpu.irqs[0]++;
timer_tick_interrupt(regs);
}
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index f2f9c9d0540c..2af4669e3396 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -116,6 +116,14 @@ extern unsigned long pfn_base;
extern unsigned int sys_call_table[];
+extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
+extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *);
+extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *);
+extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
+ unsigned long *, unsigned long *, unsigned long *);
+
/* used by various drivers */
#ifdef CONFIG_SMP
#ifndef CONFIG_DEBUG_SPINLOCK
@@ -376,3 +384,8 @@ EXPORT_SYMBOL(ns87303_lock);
EXPORT_SYMBOL_GPL(sys_call_table);
EXPORT_SYMBOL(tick_ops);
+
+EXPORT_SYMBOL(xor_vis_2);
+EXPORT_SYMBOL(xor_vis_3);
+EXPORT_SYMBOL(xor_vis_4);
+EXPORT_SYMBOL(xor_vis_5);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index bfeedd653c24..3ae4b144b27f 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -12,6 +12,7 @@
#include <linux/config.h>
#include <linux/sched.h> /* for jiffies */
#include <linux/kernel.h>
+#include <linux/kallsyms.h>
#include <linux/signal.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
@@ -1644,7 +1645,9 @@ void die_if_kernel(char *str, struct pt_regs *regs)
(char *) rw < ((char *) current)
+ sizeof (union thread_union) &&
!(((unsigned long) rw) & 0x7)) {
- printk("Caller[%016lx]\n", rw->ins[7]);
+ printk("Caller[%016lx]", rw->ins[7]);
+ print_symbol(": %s\n", rw->ins[7]);
+ printk("\n");
lastrw = rw;
rw = (struct reg_window *)
(rw->ins[6] + STACK_BIAS);
diff --git a/arch/sparc64/lib/Makefile b/arch/sparc64/lib/Makefile
index bc822e42b2c9..394c4e2914d1 100644
--- a/arch/sparc64/lib/Makefile
+++ b/arch/sparc64/lib/Makefile
@@ -10,4 +10,4 @@ lib-y := PeeCeeI.o blockops.o debuglocks.o strlen.o strncmp.o \
VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \
VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \
dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \
- U3copy_in_user.o mcount.o ipcsum.o rwsem.o
+ U3copy_in_user.o mcount.o ipcsum.o rwsem.o xor.o
diff --git a/arch/sparc64/lib/xor.S b/arch/sparc64/lib/xor.S
new file mode 100644
index 000000000000..8eeba353dee4
--- /dev/null
+++ b/arch/sparc64/lib/xor.S
@@ -0,0 +1,356 @@
+/*
+ * arch/sparc64/lib/xor.S
+ *
+ * High speed xor_block operation for RAID4/5 utilizing the
+ * UltraSparc Visual Instruction Set.
+ *
+ * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz)
+ */
+
+#include <asm/visasm.h>
+#include <asm/asi.h>
+#include <asm/dcu.h>
+#include <asm/spitfire.h>
+
+/*
+ * Requirements:
+ * !(((long)dest | (long)sourceN) & (64 - 1)) &&
+ * !(len & 127) && len >= 256
+ */
+ .text
+ .globl xor_vis_2
+ .type xor_vis_2,@function
+xor_vis_2:
+ rd %fprs, %o5
+ andcc %o5, FPRS_FEF|FPRS_DU, %g0
+ be,pt %icc, 0f
+ sethi %hi(VISenter), %g1
+ jmpl %g1 + %lo(VISenter), %g7
+ add %g7, 8, %g7
+0: wr %g0, FPRS_FEF, %fprs
+ rd %asi, %g1
+ wr %g0, ASI_BLK_P, %asi
+ membar #LoadStore|#StoreLoad|#StoreStore
+ sub %o0, 128, %o0
+ ldda [%o1] %asi, %f0
+ ldda [%o2] %asi, %f16
+
+2: ldda [%o1 + 64] %asi, %f32
+ fxor %f0, %f16, %f16
+ fxor %f2, %f18, %f18
+ fxor %f4, %f20, %f20
+ fxor %f6, %f22, %f22
+ fxor %f8, %f24, %f24
+ fxor %f10, %f26, %f26
+ fxor %f12, %f28, %f28
+ fxor %f14, %f30, %f30
+ stda %f16, [%o1] %asi
+ ldda [%o2 + 64] %asi, %f48
+ ldda [%o1 + 128] %asi, %f0
+ fxor %f32, %f48, %f48
+ fxor %f34, %f50, %f50
+ add %o1, 128, %o1
+ fxor %f36, %f52, %f52
+ add %o2, 128, %o2
+ fxor %f38, %f54, %f54
+ subcc %o0, 128, %o0
+ fxor %f40, %f56, %f56
+ fxor %f42, %f58, %f58
+ fxor %f44, %f60, %f60
+ fxor %f46, %f62, %f62
+ stda %f48, [%o1 - 64] %asi
+ bne,pt %xcc, 2b
+ ldda [%o2] %asi, %f16
+
+ ldda [%o1 + 64] %asi, %f32
+ fxor %f0, %f16, %f16
+ fxor %f2, %f18, %f18
+ fxor %f4, %f20, %f20
+ fxor %f6, %f22, %f22
+ fxor %f8, %f24, %f24
+ fxor %f10, %f26, %f26
+ fxor %f12, %f28, %f28
+ fxor %f14, %f30, %f30
+ stda %f16, [%o1] %asi
+ ldda [%o2 + 64] %asi, %f48
+ membar #Sync
+ fxor %f32, %f48, %f48
+ fxor %f34, %f50, %f50
+ fxor %f36, %f52, %f52
+ fxor %f38, %f54, %f54
+ fxor %f40, %f56, %f56
+ fxor %f42, %f58, %f58
+ fxor %f44, %f60, %f60
+ fxor %f46, %f62, %f62
+ stda %f48, [%o1 + 64] %asi
+ membar #Sync|#StoreStore|#StoreLoad
+ wr %g1, %g0, %asi
+ retl
+ wr %g0, 0, %fprs
+ .size xor_vis_2, .-xor_vis_2
+
+
+ .globl xor_vis_3
+ .type xor_vis_3,@function
+xor_vis_3:
+ rd %fprs, %o5
+ andcc %o5, FPRS_FEF|FPRS_DU, %g0
+ be,pt %icc, 0f
+ sethi %hi(VISenter), %g1
+ jmpl %g1 + %lo(VISenter), %g7
+ add %g7, 8, %g7
+0: wr %g0, FPRS_FEF, %fprs
+ rd %asi, %g1
+ wr %g0, ASI_BLK_P, %asi
+ membar #LoadStore|#StoreLoad|#StoreStore
+ sub %o0, 64, %o0
+ ldda [%o1] %asi, %f0
+ ldda [%o2] %asi, %f16
+
+3: ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f48
+ fxor %f2, %f18, %f50
+ add %o1, 64, %o1
+ fxor %f4, %f20, %f52
+ fxor %f6, %f22, %f54
+ add %o2, 64, %o2
+ fxor %f8, %f24, %f56
+ fxor %f10, %f26, %f58
+ fxor %f12, %f28, %f60
+ fxor %f14, %f30, %f62
+ ldda [%o1] %asi, %f0
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ add %o3, 64, %o3
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ subcc %o0, 64, %o0
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ stda %f48, [%o1 - 64] %asi
+ bne,pt %xcc, 3b
+ ldda [%o2] %asi, %f16
+
+ ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f48
+ fxor %f2, %f18, %f50
+ fxor %f4, %f20, %f52
+ fxor %f6, %f22, %f54
+ fxor %f8, %f24, %f56
+ fxor %f10, %f26, %f58
+ fxor %f12, %f28, %f60
+ fxor %f14, %f30, %f62
+ membar #Sync
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ stda %f48, [%o1] %asi
+ membar #Sync|#StoreStore|#StoreLoad
+ wr %g1, %g0, %asi
+ retl
+ wr %g0, 0, %fprs
+ .size xor_vis_3, .-xor_vis_3
+
+
+ .globl xor_vis_4
+ .type xor_vis_4,@function
+xor_vis_4:
+ rd %fprs, %o5
+ andcc %o5, FPRS_FEF|FPRS_DU, %g0
+ be,pt %icc, 0f
+ sethi %hi(VISenter), %g1
+ jmpl %g1 + %lo(VISenter), %g7
+ add %g7, 8, %g7
+0: wr %g0, FPRS_FEF, %fprs
+ rd %asi, %g1
+ wr %g0, ASI_BLK_P, %asi
+ membar #LoadStore|#StoreLoad|#StoreStore
+ sub %o0, 64, %o0
+ ldda [%o1] %asi, %f0
+ ldda [%o2] %asi, %f16
+
+4: ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f16
+ fxor %f2, %f18, %f18
+ add %o1, 64, %o1
+ fxor %f4, %f20, %f20
+ fxor %f6, %f22, %f22
+ add %o2, 64, %o2
+ fxor %f8, %f24, %f24
+ fxor %f10, %f26, %f26
+ fxor %f12, %f28, %f28
+ fxor %f14, %f30, %f30
+ ldda [%o4] %asi, %f48
+ fxor %f16, %f32, %f32
+ fxor %f18, %f34, %f34
+ fxor %f20, %f36, %f36
+ fxor %f22, %f38, %f38
+ add %o3, 64, %o3
+ fxor %f24, %f40, %f40
+ fxor %f26, %f42, %f42
+ fxor %f28, %f44, %f44
+ fxor %f30, %f46, %f46
+ ldda [%o1] %asi, %f0
+ fxor %f32, %f48, %f48
+ fxor %f34, %f50, %f50
+ fxor %f36, %f52, %f52
+ add %o4, 64, %o4
+ fxor %f38, %f54, %f54
+ fxor %f40, %f56, %f56
+ fxor %f42, %f58, %f58
+ subcc %o0, 64, %o0
+ fxor %f44, %f60, %f60
+ fxor %f46, %f62, %f62
+ stda %f48, [%o1 - 64] %asi
+ bne,pt %xcc, 4b
+ ldda [%o2] %asi, %f16
+
+ ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f16
+ fxor %f2, %f18, %f18
+ fxor %f4, %f20, %f20
+ fxor %f6, %f22, %f22
+ fxor %f8, %f24, %f24
+ fxor %f10, %f26, %f26
+ fxor %f12, %f28, %f28
+ fxor %f14, %f30, %f30
+ ldda [%o4] %asi, %f48
+ fxor %f16, %f32, %f32
+ fxor %f18, %f34, %f34
+ fxor %f20, %f36, %f36
+ fxor %f22, %f38, %f38
+ fxor %f24, %f40, %f40
+ fxor %f26, %f42, %f42
+ fxor %f28, %f44, %f44
+ fxor %f30, %f46, %f46
+ membar #Sync
+ fxor %f32, %f48, %f48
+ fxor %f34, %f50, %f50
+ fxor %f36, %f52, %f52
+ fxor %f38, %f54, %f54
+ fxor %f40, %f56, %f56
+ fxor %f42, %f58, %f58
+ fxor %f44, %f60, %f60
+ fxor %f46, %f62, %f62
+ stda %f48, [%o1] %asi
+ membar #Sync|#StoreStore|#StoreLoad
+ wr %g1, %g0, %asi
+ retl
+ wr %g0, 0, %fprs
+ .size xor_vis_4, .-xor_vis_4
+
+
+ .globl xor_vis_5
+ .type xor_vis_5,@function
+xor_vis_5:
+ mov %o5, %g5
+ rd %fprs, %o5
+ andcc %o5, FPRS_FEF|FPRS_DU, %g0
+ be,pt %icc, 0f
+ sethi %hi(VISenter), %g1
+ jmpl %g1 + %lo(VISenter), %g7
+ add %g7, 8, %g7
+0: wr %g0, FPRS_FEF, %fprs
+ mov %g5, %o5
+ rd %asi, %g1
+ wr %g0, ASI_BLK_P, %asi
+ membar #LoadStore|#StoreLoad|#StoreStore
+ sub %o0, 64, %o0
+ ldda [%o1] %asi, %f0
+ ldda [%o2] %asi, %f16
+
+5: ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f48
+ fxor %f2, %f18, %f50
+ add %o1, 64, %o1
+ fxor %f4, %f20, %f52
+ fxor %f6, %f22, %f54
+ add %o2, 64, %o2
+ fxor %f8, %f24, %f56
+ fxor %f10, %f26, %f58
+ fxor %f12, %f28, %f60
+ fxor %f14, %f30, %f62
+ ldda [%o4] %asi, %f16
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ add %o3, 64, %o3
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ ldda [%o5] %asi, %f32
+ fxor %f48, %f16, %f48
+ fxor %f50, %f18, %f50
+ add %o4, 64, %o4
+ fxor %f52, %f20, %f52
+ fxor %f54, %f22, %f54
+ add %o5, 64, %o5
+ fxor %f56, %f24, %f56
+ fxor %f58, %f26, %f58
+ fxor %f60, %f28, %f60
+ fxor %f62, %f30, %f62
+ ldda [%o1] %asi, %f0
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ subcc %o0, 64, %o0
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ stda %f48, [%o1 - 64] %asi
+ bne,pt %xcc, 5b
+ ldda [%o2] %asi, %f16
+
+ ldda [%o3] %asi, %f32
+ fxor %f0, %f16, %f48
+ fxor %f2, %f18, %f50
+ fxor %f4, %f20, %f52
+ fxor %f6, %f22, %f54
+ fxor %f8, %f24, %f56
+ fxor %f10, %f26, %f58
+ fxor %f12, %f28, %f60
+ fxor %f14, %f30, %f62
+ ldda [%o4] %asi, %f16
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ ldda [%o5] %asi, %f32
+ fxor %f48, %f16, %f48
+ fxor %f50, %f18, %f50
+ fxor %f52, %f20, %f52
+ fxor %f54, %f22, %f54
+ fxor %f56, %f24, %f56
+ fxor %f58, %f26, %f58
+ fxor %f60, %f28, %f60
+ fxor %f62, %f30, %f62
+ membar #Sync
+ fxor %f48, %f32, %f48
+ fxor %f50, %f34, %f50
+ fxor %f52, %f36, %f52
+ fxor %f54, %f38, %f54
+ fxor %f56, %f40, %f56
+ fxor %f58, %f42, %f58
+ fxor %f60, %f44, %f60
+ fxor %f62, %f46, %f62
+ stda %f48, [%o1] %asi
+ membar #Sync|#StoreStore|#StoreLoad
+ wr %g1, %g0, %asi
+ retl
+ wr %g0, 0, %fprs
+ .size xor_vis_5, .-xor_vis_5
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 9f0fba361776..18c53d71658e 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -113,8 +113,9 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
}
void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
+ unsigned cpu = smp_processor_id();
if (prev != next)
clear_bit(cpu, &prev->cpu_vm_mask);
set_bit(cpu, &next->cpu_vm_mask);
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 496dfa9da747..e4b86e6cbf9b 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -14,6 +14,8 @@
#include <linux/string.h>
#include <linux/binfmts.h>
#include <linux/mm.h>
+#include <linux/security.h>
+
#include <asm/segment.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@@ -339,7 +341,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
if (!mpnt)
return -ENOMEM;
- if (!vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+ if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
kmem_cache_free(vm_area_cachep, mpnt);
return -ENOMEM;
}
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 6b71af1d1060..82a75fa6b67e 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -288,7 +288,7 @@ void __init cpu_init (void)
me->active_mm = &init_mm;
if (me->mm)
BUG();
- enter_lazy_tlb(&init_mm, me, cpu);
+ enter_lazy_tlb(&init_mm, me);
set_tss_desc(cpu, t);
load_TR_desc();
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index 3be6a8e4b679..cafd352ba636 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -64,7 +64,7 @@ void show_mem(void)
printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
- for (i = 0; i < pgdat->node_size; ++i) {
+ for (i = 0; i < pgdat->node_spanned_pages; ++i) {
page = pgdat->node_mem_map + i;
total++;
if (PageReserved(page))
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index 0150d11586a7..738ae097faeb 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -86,7 +86,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
NODE_DATA(nodeid)->node_start_pfn = start_pfn;
- NODE_DATA(nodeid)->node_size = end_pfn - start_pfn;
+ NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
/* Find a place for the bootmem map */
bootmap_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index ea551b8dc28b..2a9c349bd7c9 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -3,6 +3,8 @@
*
* Copyright (c) 2002-3 Patrick Mochel
* Copyright (c) 2002-3 Open Source Development Labs
+ * Copyright (c) 2003 Greg Kroah-Hartman
+ * Copyright (c) 2003 IBM Corp.
*
* This file is released under the GPLv2
*
@@ -339,6 +341,24 @@ void class_device_unregister(struct class_device *class_dev)
class_device_put(class_dev);
}
+int class_device_rename(struct class_device *class_dev, char *new_name)
+{
+ class_dev = class_device_get(class_dev);
+ if (!class_dev)
+ return -EINVAL;
+
+ pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
+ new_name);
+
+ strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
+
+ kobject_rename(&class_dev->kobj, new_name);
+
+ class_device_put(class_dev);
+
+ return 0;
+}
+
struct class_device * class_device_get(struct class_device *class_dev)
{
if (class_dev)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b186dba8d2d8..f3981af94570 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -149,7 +149,7 @@ firmware_data_read(struct kobject *kobj,
if (offset + count > fw->size)
count = fw->size - offset;
- memcpy(buffer, fw->data + offset, count);
+ memcpy(buffer + offset, fw->data + offset, count);
return count;
}
static int
@@ -198,7 +198,7 @@ firmware_data_write(struct kobject *kobj,
if (retval)
return retval;
- memcpy(fw->data + offset, buffer, count);
+ memcpy(fw->data + offset, buffer + offset, count);
fw->size = max_t(size_t, offset + count, fw->size);
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index c723e8ecc584..4733ec79a6d0 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -8,7 +8,13 @@
# In the future, some of these should be built conditionally.
#
-obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o deadline-iosched.o
+#
+# NOTE that ll_rw_blk.c must come early in linkage order - it starts the
+# kblockd threads
+#
+
+obj-y := elevator.o ll_rw_blk.o ioctl.o genhd.o scsi_ioctl.o \
+ deadline-iosched.o as-iosched.o
obj-$(CONFIG_MAC_FLOPPY) += swim3.o
obj-$(CONFIG_BLK_DEV_FD) += floppy.o
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
new file mode 100644
index 000000000000..b19289348fb0
--- /dev/null
+++ b/drivers/block/as-iosched.c
@@ -0,0 +1,1837 @@
+/*
+ * linux/drivers/block/as-iosched.c
+ *
+ * Anticipatory & deadline i/o scheduler.
+ *
+ * Copyright (C) 2002 Jens Axboe <axboe@suse.de>
+ * Nick Piggin <piggin@cyberone.com.au>
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/blk.h>
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+#include <linux/hash.h>
+#include <linux/rbtree.h>
+#include <linux/interrupt.h>
+
+#define REQ_SYNC 1
+#define REQ_ASYNC 0
+
+/*
+ * See Documentation/as-iosched.txt
+ */
+
+/*
+ * max time before a read is submitted.
+ */
+#define default_read_expire (HZ / 20)
+
+/*
+ * ditto for writes, these limits are not hard, even
+ * if the disk is capable of satisfying them.
+ */
+#define default_write_expire (HZ / 5)
+
+/*
+ * read_batch_expire describes how long we will allow a stream of reads to
+ * persist before looking to see whether it is time to switch over to writes.
+ */
+#define default_read_batch_expire (HZ / 5)
+
+/*
+ * write_batch_expire describes how long we want a stream of writes to run for.
+ * This is not a hard limit, but a target we set for the auto-tuning thingy.
+ * See, the problem is: we can send a lot of writes to disk cache / TCQ in
+ * a short amount of time...
+ */
+#define default_write_batch_expire (HZ / 20)
+
+/*
+ * max time we may wait to anticipate a read (default around 6ms)
+ */
+#define default_antic_expire ((HZ / 150) ? HZ / 150 : 1)
+
+/*
+ * Keep track of up to 20ms thinktimes. We can go as big as we like here,
+ * however huge values tend to interfere and not decay fast enough. A program
+ * might be in a non-io phase of operation. Waiting on user input for example,
+ * or doing a lengthy computation. A small penalty can be justified there, and
+ * will still catch out those processes that constantly have large thinktimes.
+ */
+#define MAX_THINKTIME (HZ/50UL)
+
+/* Bits in as_io_context.state */
+enum as_io_states {
+ AS_TASK_RUNNING=0, /* Process has not exitted */
+ AS_TASK_IORUNNING, /* Process has completed some IO */
+};
+
+enum anticipation_status {
+ ANTIC_OFF=0, /* Not anticipating (normal operation) */
+ ANTIC_WAIT_REQ, /* The last read has not yet completed */
+ ANTIC_WAIT_NEXT, /* Currently anticipating a request vs
+ last read (which has completed) */
+ ANTIC_FINISHED, /* Anticipating but have found a candidate
+ * or timed out */
+};
+
+struct as_data {
+ /*
+ * run time data
+ */
+
+ struct request_queue *q; /* the "owner" queue */
+
+ /*
+ * requests (as_rq s) are present on both sort_list and fifo_list
+ */
+ struct rb_root sort_list[2];
+ struct list_head fifo_list[2];
+
+ struct as_rq *next_arq[2]; /* next in sort order */
+ sector_t last_sector[2]; /* last REQ_SYNC & REQ_ASYNC sectors */
+ struct list_head *dispatch; /* driver dispatch queue */
+ struct list_head *hash; /* request hash */
+ unsigned long hash_valid_count; /* barrier hash count */
+ unsigned long current_batch_expires;
+ unsigned long last_check_fifo[2];
+ int changed_batch;
+ int batch_data_dir; /* current batch REQ_SYNC / REQ_ASYNC */
+ int write_batch_count; /* max # of reqs in a write batch */
+ int current_write_count; /* how many requests left this batch */
+ int write_batch_idled; /* has the write batch gone idle? */
+ mempool_t *arq_pool;
+
+ enum anticipation_status antic_status;
+ unsigned long antic_start; /* jiffies: when it started */
+ struct timer_list antic_timer; /* anticipatory scheduling timer */
+ struct work_struct antic_work; /* Deferred unplugging */
+ struct io_context *io_context; /* Identify the expected process */
+ int ioc_finished; /* IO associated with io_context is finished */
+ int nr_dispatched;
+
+ /*
+ * settings that change how the i/o scheduler behaves
+ */
+ unsigned long fifo_expire[2];
+ unsigned long batch_expire[2];
+ unsigned long antic_expire;
+};
+
+#define list_entry_fifo(ptr) list_entry((ptr), struct as_rq, fifo)
+
+/*
+ * per-request data.
+ */
+enum arq_state {
+ AS_RQ_NEW=0, /* New - not referenced and not on any lists */
+ AS_RQ_QUEUED, /* In the request queue. It belongs to the
+ scheduler */
+ AS_RQ_DISPATCHED, /* On the dispatch list. It belongs to the
+ driver now */
+};
+
+struct as_rq {
+ /*
+ * rbtree index, key is the starting offset
+ */
+ struct rb_node rb_node;
+ sector_t rb_key;
+
+ struct request *request;
+
+ struct io_context *io_context; /* The submitting task */
+
+ /*
+ * request hash, key is the ending offset (for back merge lookup)
+ */
+ struct list_head hash;
+ unsigned long hash_valid_count;
+
+ /*
+ * expire fifo
+ */
+ struct list_head fifo;
+ unsigned long expires;
+
+ int is_sync;
+ enum arq_state state; /* debug only */
+};
+
+#define RQ_DATA(rq) ((struct as_rq *) (rq)->elevator_private)
+
+static kmem_cache_t *arq_pool;
+
+/*
+ * IO Context helper functions
+ */
+/* Debug */
+static atomic_t nr_as_io_requests = ATOMIC_INIT(0);
+
+/* Called to deallocate the as_io_context */
+static void free_as_io_context(struct as_io_context *aic)
+{
+ atomic_dec(&nr_as_io_requests);
+ kfree(aic);
+}
+
+/* Called when the task exits */
+static void exit_as_io_context(struct as_io_context *aic)
+{
+ clear_bit(AS_TASK_RUNNING, &aic->state);
+}
+
+static struct as_io_context *alloc_as_io_context(void)
+{
+ struct as_io_context *ret;
+
+ ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+ if (ret) {
+ atomic_inc(&nr_as_io_requests);
+ ret->dtor = free_as_io_context;
+ ret->exit = exit_as_io_context;
+ ret->state = 1 << AS_TASK_RUNNING;
+ atomic_set(&ret->nr_queued, 0);
+ atomic_set(&ret->nr_dispatched, 0);
+ spin_lock_init(&ret->lock);
+ ret->ttime_total = 0;
+ ret->ttime_samples = 0;
+ ret->ttime_mean = 0;
+ ret->seek_total = 0;
+ ret->seek_samples = 0;
+ ret->seek_mean = 0;
+ }
+
+ return ret;
+}
+
+/*
+ * If the current task has no AS IO context then create one and initialise it.
+ * Then take a ref on the task's io context and return it.
+ */
+static struct io_context *as_get_io_context(void)
+{
+ struct io_context *ioc = get_io_context(GFP_ATOMIC);
+ if (ioc && !ioc->aic) {
+ ioc->aic = alloc_as_io_context();
+ if (!ioc->aic) {
+ put_io_context(ioc);
+ ioc = NULL;
+ }
+ }
+ return ioc;
+}
+
+/*
+ * the back merge hash support functions
+ */
+static const int as_hash_shift = 6;
+#define AS_HASH_BLOCK(sec) ((sec) >> 3)
+#define AS_HASH_FN(sec) (hash_long(AS_HASH_BLOCK((sec)), as_hash_shift))
+#define AS_HASH_ENTRIES (1 << as_hash_shift)
+#define rq_hash_key(rq) ((rq)->sector + (rq)->nr_sectors)
+#define list_entry_hash(ptr) list_entry((ptr), struct as_rq, hash)
+#define ON_HASH(arq) (arq)->hash_valid_count
+
+#define AS_INVALIDATE_HASH(ad) \
+ do { \
+ if (!++(ad)->hash_valid_count) \
+ (ad)->hash_valid_count = 1; \
+ } while (0)
+
+static inline void __as_del_arq_hash(struct as_rq *arq)
+{
+ arq->hash_valid_count = 0;
+ list_del_init(&arq->hash);
+}
+
+static inline void as_del_arq_hash(struct as_rq *arq)
+{
+ if (ON_HASH(arq))
+ __as_del_arq_hash(arq);
+}
+
+static void as_remove_merge_hints(request_queue_t *q, struct as_rq *arq)
+{
+ as_del_arq_hash(arq);
+
+ if (q->last_merge == &arq->request->queuelist)
+ q->last_merge = NULL;
+}
+
+static void as_add_arq_hash(struct as_data *ad, struct as_rq *arq)
+{
+ struct request *rq = arq->request;
+
+ BUG_ON(ON_HASH(arq));
+
+ arq->hash_valid_count = ad->hash_valid_count;
+ list_add(&arq->hash, &ad->hash[AS_HASH_FN(rq_hash_key(rq))]);
+}
+
+/*
+ * move hot entry to front of chain
+ */
+static inline void as_hot_arq_hash(struct as_data *ad, struct as_rq *arq)
+{
+ struct request *rq = arq->request;
+ struct list_head *head = &ad->hash[AS_HASH_FN(rq_hash_key(rq))];
+
+ if (!ON_HASH(arq)) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (arq->hash.prev != head) {
+ list_del(&arq->hash);
+ list_add(&arq->hash, head);
+ }
+}
+
+static struct request *as_find_arq_hash(struct as_data *ad, sector_t offset)
+{
+ struct list_head *hash_list = &ad->hash[AS_HASH_FN(offset)];
+ struct list_head *entry, *next = hash_list->next;
+
+ while ((entry = next) != hash_list) {
+ struct as_rq *arq = list_entry_hash(entry);
+ struct request *__rq = arq->request;
+
+ next = entry->next;
+
+ BUG_ON(!ON_HASH(arq));
+
+ if (!rq_mergeable(__rq)
+ || arq->hash_valid_count != ad->hash_valid_count) {
+ __as_del_arq_hash(arq);
+ continue;
+ }
+
+ if (rq_hash_key(__rq) == offset)
+ return __rq;
+ }
+
+ return NULL;
+}
+
+/*
+ * rb tree support functions
+ */
+#define RB_NONE (2)
+#define RB_EMPTY(root) ((root)->rb_node == NULL)
+#define ON_RB(node) ((node)->rb_color != RB_NONE)
+#define RB_CLEAR(node) ((node)->rb_color = RB_NONE)
+#define rb_entry_arq(node) rb_entry((node), struct as_rq, rb_node)
+#define ARQ_RB_ROOT(ad, arq) (&(ad)->sort_list[(arq)->is_sync])
+#define rq_rb_key(rq) (rq)->sector
+
+/*
+ * as_find_first_arq finds the first (lowest sector numbered) request
+ * for the specified data_dir. Used to sweep back to the start of the disk
+ * (1-way elevator) after we process the last (highest sector) request.
+ */
+static struct as_rq *as_find_first_arq(struct as_data *ad, int data_dir)
+{
+ struct rb_node *n = ad->sort_list[data_dir].rb_node;
+
+ if (n == NULL)
+ return NULL;
+
+ for (;;) {
+ if (n->rb_left == NULL)
+ return rb_entry_arq(n);
+
+ n = n->rb_left;
+ }
+}
+
+static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+ struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node;
+ struct rb_node *parent = NULL;
+ struct as_rq *__arq;
+
+ while (*p) {
+ parent = *p;
+ __arq = rb_entry_arq(parent);
+
+ if (arq->rb_key < __arq->rb_key)
+ p = &(*p)->rb_left;
+ else if (arq->rb_key > __arq->rb_key)
+ p = &(*p)->rb_right;
+ else
+ return __arq;
+ }
+
+ rb_link_node(&arq->rb_node, parent, p);
+ return 0;
+}
+
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq);
+/*
+ * Add the request to the rb tree if it is unique. If there is an alias (an
+ * existing request against the same sector), which can happen when using
+ * direct IO, then move the alias to the dispatch list and then add the
+ * request.
+ */
+static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+ struct as_rq *alias;
+ struct request *rq = arq->request;
+
+ arq->rb_key = rq_rb_key(rq);
+
+ /* This can be caused by direct IO */
+ while ((alias = __as_add_arq_rb(ad, arq)))
+ as_move_to_dispatch(ad, alias);
+
+ rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
+}
+
+static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq)
+{
+ if (!ON_RB(&arq->rb_node)) {
+ WARN_ON(1);
+ return;
+ }
+
+ rb_erase(&arq->rb_node, ARQ_RB_ROOT(ad, arq));
+ RB_CLEAR(&arq->rb_node);
+}
+
+static struct request *
+as_find_arq_rb(struct as_data *ad, sector_t sector, int data_dir)
+{
+ struct rb_node *n = ad->sort_list[data_dir].rb_node;
+ struct as_rq *arq;
+
+ while (n) {
+ arq = rb_entry_arq(n);
+
+ if (sector < arq->rb_key)
+ n = n->rb_left;
+ else if (sector > arq->rb_key)
+ n = n->rb_right;
+ else
+ return arq->request;
+ }
+
+ return NULL;
+}
+
+/*
+ * IO Scheduler proper
+ */
+
+#define MAXBACK (1024 * 1024) /*
+ * Maximum distance the disk will go backward
+ * for a request.
+ */
+
+/*
+ * as_choose_req selects the preferred one of two requests of the same data_dir
+ * ignoring time - eg. timeouts, which is the job of as_dispatch_request
+ */
+static struct as_rq *
+as_choose_req(struct as_data *ad, struct as_rq *arq1, struct as_rq *arq2)
+{
+ int data_dir;
+ sector_t last, s1, s2, d1, d2;
+ int r1_wrap=0, r2_wrap=0; /* requests are behind the disk head */
+ const sector_t maxback = MAXBACK;
+
+ if (arq1 == NULL || arq1 == arq2)
+ return arq2;
+ if (arq2 == NULL)
+ return arq1;
+
+ data_dir = arq1->is_sync;
+
+ last = ad->last_sector[data_dir];
+ s1 = arq1->request->sector;
+ s2 = arq2->request->sector;
+
+ BUG_ON(data_dir != arq2->is_sync);
+
+ /*
+ * Strict one way elevator _except_ in the case where we allow
+ * short backward seeks which are biased as twice the cost of a
+ * similar forward seek.
+ */
+ if (s1 >= last)
+ d1 = s1 - last;
+ else if (s1+maxback >= last)
+ d1 = (last - s1)*2;
+ else {
+ r1_wrap = 1;
+ d1 = 0; /* shut up, gcc */
+ }
+
+ if (s2 >= last)
+ d2 = s2 - last;
+ else if (s2+maxback >= last)
+ d2 = (last - s2)*2;
+ else {
+ r2_wrap = 1;
+ d2 = 0;
+ }
+
+ /* Found required data */
+ if (!r1_wrap && r2_wrap)
+ return arq1;
+ else if (!r2_wrap && r1_wrap)
+ return arq2;
+ else if (r1_wrap && r2_wrap) {
+ /* both behind the head */
+ if (s1 <= s2)
+ return arq1;
+ else
+ return arq2;
+ }
+
+ /* Both requests in front of the head */
+ if (d1 < d2)
+ return arq1;
+ else if (d2 < d1)
+ return arq2;
+ else {
+ if (s1 >= s2)
+ return arq1;
+ else
+ return arq2;
+ }
+}
+
+/*
+ * as_find_next_arq finds the next request after @prev in elevator order.
+ * this with as_choose_req form the basis for how the scheduler chooses
+ * what request to process next. Anticipation works on top of this.
+ */
+static struct as_rq *as_find_next_arq(struct as_data *ad, struct as_rq *last)
+{
+ const int data_dir = last->is_sync;
+ struct as_rq *ret;
+ struct rb_node *rbnext = rb_next(&last->rb_node);
+ struct rb_node *rbprev = rb_prev(&last->rb_node);
+ struct as_rq *arq_next, *arq_prev;
+
+ BUG_ON(!ON_RB(&last->rb_node));
+
+ if (rbprev)
+ arq_prev = rb_entry_arq(rbprev);
+ else
+ arq_prev = NULL;
+
+ if (rbnext)
+ arq_next = rb_entry_arq(rbnext);
+ else {
+ arq_next = as_find_first_arq(ad, data_dir);
+ if (arq_next == last)
+ arq_next = NULL;
+ }
+
+ ret = as_choose_req(ad, arq_next, arq_prev);
+
+ return ret;
+}
+
+/*
+ * anticipatory scheduling functions follow
+ */
+
+/*
+ * as_antic_expired tells us when we have anticipated too long.
+ * The funny "absolute difference" math on the elapsed time is to handle
+ * jiffy wraps, and disks which have been idle for 0x80000000 jiffies.
+ */
+static int as_antic_expired(struct as_data *ad)
+{
+ long delta_jif;
+
+ delta_jif = jiffies - ad->antic_start;
+ if (unlikely(delta_jif < 0))
+ delta_jif = -delta_jif;
+ if (delta_jif < ad->antic_expire)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * as_antic_waitnext starts anticipating that a nice request will soon be
+ * submitted. See also as_antic_waitreq
+ */
+static void as_antic_waitnext(struct as_data *ad)
+{
+ unsigned long timeout;
+
+ BUG_ON(ad->antic_status != ANTIC_OFF
+ && ad->antic_status != ANTIC_WAIT_REQ);
+
+ timeout = ad->antic_start + ad->antic_expire;
+
+ mod_timer(&ad->antic_timer, timeout);
+
+ ad->antic_status = ANTIC_WAIT_NEXT;
+}
+
+/*
+ * as_antic_waitreq starts anticipating. We don't start timing the anticipation
+ * until the request that we're anticipating on has finished. This means we
+ * are timing from when the candidate process wakes up hopefully.
+ */
+static void as_antic_waitreq(struct as_data *ad)
+{
+ BUG_ON(ad->antic_status == ANTIC_FINISHED);
+ if (ad->antic_status == ANTIC_OFF) {
+ if (!ad->io_context || ad->ioc_finished)
+ as_antic_waitnext(ad);
+ else
+ ad->antic_status = ANTIC_WAIT_REQ;
+ }
+}
+
+/*
+ * This is called directly by the functions in this file to stop anticipation.
+ * We kill the timer and schedule a call to the request_fn asap.
+ */
+static void as_antic_stop(struct as_data *ad)
+{
+ int status = ad->antic_status;
+
+ if (status == ANTIC_WAIT_REQ || status == ANTIC_WAIT_NEXT) {
+ if (status == ANTIC_WAIT_NEXT)
+ del_timer(&ad->antic_timer);
+ ad->antic_status = ANTIC_FINISHED;
+ /* see as_work_handler */
+ kblockd_schedule_work(&ad->antic_work);
+ }
+}
+
+/*
+ * as_antic_timeout is the timer function set by as_antic_waitnext.
+ */
+static void as_antic_timeout(unsigned long data)
+{
+ struct request_queue *q = (struct request_queue *)data;
+ struct as_data *ad = q->elevator.elevator_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ if (ad->antic_status == ANTIC_WAIT_REQ
+ || ad->antic_status == ANTIC_WAIT_NEXT) {
+ ad->antic_status = ANTIC_FINISHED;
+ kblockd_schedule_work(&ad->antic_work);
+ }
+ spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+/*
+ * as_close_req decides if one request is considered "close" to the
+ * previous one issued.
+ */
+static int as_close_req(struct as_data *ad, struct as_rq *arq)
+{
+ unsigned long delay; /* milliseconds */
+ sector_t last = ad->last_sector[ad->batch_data_dir];
+ sector_t next = arq->request->sector;
+ sector_t delta; /* acceptable close offset (in sectors) */
+
+ if (ad->antic_status == ANTIC_OFF || !ad->ioc_finished)
+ delay = 0;
+ else
+ delay = ((jiffies - ad->antic_start) * 1000) / HZ;
+
+ if (delay <= 1)
+ delta = 64;
+ else if (delay <= 20 && delay <= ad->antic_expire)
+ delta = 64 << (delay-1);
+ else
+ return 1;
+
+ return (last - (delta>>1) <= next) && (next <= last + delta);
+}
+
+/*
+ * as_can_break_anticipation returns true if we have been anticipating this
+ * request.
+ *
+ * It also returns true if the process against which we are anticipating
+ * submits a write - that's presumably an fsync, O_SYNC write, etc. We want to
+ * dispatch it ASAP, because we know that application will not be submitting
+ * any new reads.
+ *
+ * If the task which has submitted the request has exitted, break anticipation.
+ *
+ * If this task has queued some other IO, do not enter enticipation.
+ */
+static int as_can_break_anticipation(struct as_data *ad, struct as_rq *arq)
+{
+ struct io_context *ioc;
+ struct as_io_context *aic;
+
+ if (arq && arq->is_sync == REQ_SYNC && as_close_req(ad, arq)) {
+ /* close request */
+ return 1;
+ }
+
+ if (ad->ioc_finished && as_antic_expired(ad)) {
+ /*
+ * In this situation status should really be FINISHED,
+ * however the timer hasn't had the chance to run yet.
+ */
+ return 1;
+ }
+
+ ioc = ad->io_context;
+ BUG_ON(!ioc);
+
+ if (arq && ioc == arq->io_context) {
+ /* request from same process */
+ return 1;
+ }
+
+ aic = ioc->aic;
+ if (!aic)
+ return 0;
+
+ if (!test_bit(AS_TASK_RUNNING, &aic->state)) {
+ /* process anticipated on has exitted */
+ return 1;
+ }
+
+ if (atomic_read(&aic->nr_queued) > 0) {
+ /* process has more requests queued */
+ return 1;
+ }
+
+ if (atomic_read(&aic->nr_dispatched) > 0) {
+ /* process has more requests dispatched */
+ return 1;
+ }
+
+ if (aic->ttime_mean > ad->antic_expire) {
+ /* the process thinks too much between requests */
+ return 1;
+ }
+
+ if (arq && aic->seek_samples) {
+ sector_t s;
+ if (ad->last_sector[REQ_SYNC] < arq->request->sector)
+ s = arq->request->sector - ad->last_sector[REQ_SYNC];
+ else
+ s = ad->last_sector[REQ_SYNC] - arq->request->sector;
+
+ if (aic->seek_mean > (s>>1)) {
+ /* this request is better than what we're expecting */
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * as_can_anticipate indicates weather we should either run arq
+ * or keep anticipating a better request.
+ */
+static int as_can_anticipate(struct as_data *ad, struct as_rq *arq)
+{
+ if (!ad->io_context)
+ /*
+ * Last request submitted was a write
+ */
+ return 0;
+
+ if (ad->antic_status == ANTIC_FINISHED)
+ /*
+ * Don't restart if we have just finished. Run the next request
+ */
+ return 0;
+
+ if (as_can_break_anticipation(ad, arq))
+ /*
+ * This request is a good candidate. Don't keep anticipating,
+ * run it.
+ */
+ return 0;
+
+ /*
+ * OK from here, we haven't finished, and don't have a decent request!
+ * Status is either ANTIC_OFF so start waiting,
+ * ANTIC_WAIT_REQ so continue waiting for request to finish
+ * or ANTIC_WAIT_NEXT so continue waiting for an acceptable request.
+ *
+ */
+
+ return 1;
+}
+
+/*
+ * as_update_iohist keeps a decaying histogram of IO thinktimes, and
+ * updates @aic->ttime_mean based on that. It is called when a new
+ * request is queued.
+ */
+static void as_update_iohist(struct as_io_context *aic, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ int data_dir = arq->is_sync;
+ unsigned long thinktime;
+ sector_t seek_dist;
+
+ if (aic == NULL)
+ return;
+
+ if (data_dir == REQ_SYNC) {
+ spin_lock(&aic->lock);
+
+ if (test_bit(AS_TASK_IORUNNING, &aic->state)
+ && !atomic_read(&aic->nr_queued)
+ && !atomic_read(&aic->nr_dispatched)) {
+ /* Calculate read -> read thinktime */
+ thinktime = jiffies - aic->last_end_request;
+ thinktime = min(thinktime, MAX_THINKTIME-1);
+ /* fixed point: 1.0 == 1<<8 */
+ aic->ttime_samples += 256;
+ aic->ttime_total += 256*thinktime;
+ if (aic->ttime_samples)
+ /* fixed point factor is cancelled here */
+ aic->ttime_mean = (aic->ttime_total + 128)
+ / aic->ttime_samples;
+ aic->ttime_samples = (aic->ttime_samples>>1)
+ + (aic->ttime_samples>>2);
+ aic->ttime_total = (aic->ttime_total>>1)
+ + (aic->ttime_total>>2);
+ }
+
+ /* Calculate read -> read seek distance */
+ if (!aic->seek_samples)
+ seek_dist = 0;
+ else if (aic->last_request_pos < rq->sector)
+ seek_dist = rq->sector - aic->last_request_pos;
+ else
+ seek_dist = aic->last_request_pos - rq->sector;
+
+ aic->last_request_pos = rq->sector + rq->nr_sectors;
+
+ /*
+ * Don't allow the seek distance to get too large from the
+ * odd fragment, pagein, etc
+ */
+ if (aic->seek_samples < 400) /* second&third seek */
+ seek_dist = min(seek_dist, (aic->seek_mean * 4)
+ + 2*1024*1024);
+ else
+ seek_dist = min(seek_dist, (aic->seek_mean * 4)
+ + 2*1024*64);
+
+ aic->seek_samples += 256;
+ aic->seek_total += 256*seek_dist;
+ if (aic->seek_samples) {
+ aic->seek_mean = aic->seek_total + 128;
+ do_div(aic->seek_mean, aic->seek_samples);
+ }
+ aic->seek_samples = (aic->seek_samples>>1)
+ + (aic->seek_samples>>2);
+ aic->seek_total = (aic->seek_total>>1)
+ + (aic->seek_total>>2);
+
+ spin_unlock(&aic->lock);
+ }
+}
+
+/*
+ * as_update_arq must be called whenever a request (arq) is added to
+ * the sort_list. This function keeps caches up to date, and checks if the
+ * request might be one we are "anticipating"
+ */
+static void as_update_arq(struct as_data *ad, struct as_rq *arq)
+{
+ const int data_dir = arq->is_sync;
+
+ /* keep the next_arq cache up to date */
+ ad->next_arq[data_dir] = as_choose_req(ad, arq, ad->next_arq[data_dir]);
+
+ /*
+ * have we been anticipating this request?
+ * or does it come from the same process as the one we are anticipating
+ * for?
+ */
+ if (ad->antic_status == ANTIC_WAIT_REQ
+ || ad->antic_status == ANTIC_WAIT_NEXT) {
+ if (as_can_break_anticipation(ad, arq))
+ as_antic_stop(ad);
+ }
+}
+
+/*
+ * Gathers timings and resizes the write batch automatically
+ */
+void update_write_batch(struct as_data *ad)
+{
+ unsigned long batch = ad->batch_expire[REQ_ASYNC];
+ long write_time;
+
+ write_time = (jiffies - ad->current_batch_expires) + batch;
+ if (write_time < 0)
+ write_time = 0;
+
+ if (write_time > batch && !ad->write_batch_idled) {
+ if (write_time > batch * 3)
+ ad->write_batch_count /= 2;
+ else
+ ad->write_batch_count--;
+ } else if (write_time < batch && ad->current_write_count == 0) {
+ if (batch > write_time * 3)
+ ad->write_batch_count *= 2;
+ else
+ ad->write_batch_count++;
+ }
+
+ if (ad->write_batch_count < 1)
+ ad->write_batch_count = 1;
+}
+
+/*
+ * as_completed_request is to be called when a request has completed and
+ * returned something to the requesting process, be it an error or data.
+ */
+static void as_completed_request(request_queue_t *q, struct request *rq)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = RQ_DATA(rq);
+ struct as_io_context *aic;
+
+ if (unlikely(!blk_fs_request(rq)))
+ return;
+
+ WARN_ON(blk_fs_request(rq) && arq->state == AS_RQ_NEW);
+
+ if (arq->state != AS_RQ_DISPATCHED)
+ return;
+
+ if (ad->changed_batch && ad->nr_dispatched == 1) {
+ kblockd_schedule_work(&ad->antic_work);
+ ad->changed_batch = 2;
+ }
+ ad->nr_dispatched--;
+
+ /*
+ * Start counting the batch from when a request of that direction is
+ * actually serviced. This should help devices with big TCQ windows
+ * and writeback caches
+ */
+ if (ad->batch_data_dir == REQ_SYNC && ad->changed_batch
+ && ad->batch_data_dir == arq->is_sync) {
+ update_write_batch(ad);
+ ad->current_batch_expires = jiffies +
+ ad->batch_expire[REQ_SYNC];
+ ad->changed_batch = 0;
+ }
+
+ if (!arq->io_context)
+ return;
+
+ if (ad->io_context == arq->io_context) {
+ ad->antic_start = jiffies;
+ ad->ioc_finished = 1;
+ if (ad->antic_status == ANTIC_WAIT_REQ) {
+ /*
+ * We were waiting on this request, now anticipate
+ * the next one
+ */
+ as_antic_waitnext(ad);
+ }
+ }
+
+ aic = arq->io_context->aic;
+ if (!aic)
+ return;
+
+ spin_lock(&aic->lock);
+ if (arq->is_sync == REQ_SYNC) {
+ set_bit(AS_TASK_IORUNNING, &aic->state);
+ aic->last_end_request = jiffies;
+ }
+ spin_unlock(&aic->lock);
+
+ put_io_context(arq->io_context);
+}
+
+/*
+ * as_remove_queued_request removes a request from the pre dispatch queue
+ * without updating refcounts. It is expected the caller will drop the
+ * reference unless it replaces the request at somepart of the elevator
+ * (ie. the dispatch queue)
+ */
+static void as_remove_queued_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ const int data_dir = arq->is_sync;
+ struct as_data *ad = q->elevator.elevator_data;
+
+ WARN_ON(arq->state != AS_RQ_QUEUED);
+
+ if (arq->io_context && arq->io_context->aic) {
+ BUG_ON(!atomic_read(&arq->io_context->aic->nr_queued));
+ atomic_dec(&arq->io_context->aic->nr_queued);
+ }
+
+ /*
+ * Update the "next_arq" cache if we are about to remove its
+ * entry
+ */
+ if (ad->next_arq[data_dir] == arq)
+ ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+
+ list_del_init(&arq->fifo);
+ as_remove_merge_hints(q, arq);
+ as_del_arq_rb(ad, arq);
+}
+
+/*
+ * as_remove_dispatched_request is called to remove a request which has gone
+ * to the dispatch list.
+ */
+static void as_remove_dispatched_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ struct as_io_context *aic;
+
+ if (!arq) {
+ WARN_ON(1);
+ return;
+ }
+
+ WARN_ON(arq->state != AS_RQ_DISPATCHED);
+ WARN_ON(ON_RB(&arq->rb_node));
+ if (arq->io_context && arq->io_context->aic) {
+ aic = arq->io_context->aic;
+ if (aic) {
+ WARN_ON(!atomic_read(&aic->nr_dispatched));
+ atomic_dec(&aic->nr_dispatched);
+ }
+ }
+}
+/*
+ * as_remove_request is called when a driver has finished with a request.
+ * This should be only called for dispatched requests, but for some reason
+ * a POWER4 box running hwscan it does not.
+ */
+static void as_remove_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+
+ if (unlikely(!blk_fs_request(rq)))
+ return;
+
+ if (!arq) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (ON_RB(&arq->rb_node))
+ as_remove_queued_request(q, rq);
+ else
+ as_remove_dispatched_request(q, rq);
+}
+
+/*
+ * as_fifo_expired returns 0 if there are no expired reads on the fifo,
+ * 1 otherwise. It is ratelimited so that we only perform the check once per
+ * `fifo_expire' interval. Otherwise a large number of expired requests
+ * would create a hopeless seekstorm.
+ *
+ * See as_antic_expired comment.
+ */
+static int as_fifo_expired(struct as_data *ad, int adir)
+{
+ struct as_rq *arq;
+ long delta_jif;
+
+ delta_jif = jiffies - ad->last_check_fifo[adir];
+ if (unlikely(delta_jif < 0))
+ delta_jif = -delta_jif;
+ if (delta_jif < ad->fifo_expire[adir])
+ return 0;
+
+ ad->last_check_fifo[adir] = jiffies;
+
+ if (list_empty(&ad->fifo_list[adir]))
+ return 0;
+
+ arq = list_entry_fifo(ad->fifo_list[adir].next);
+
+ return time_after(jiffies, arq->expires);
+}
+
+/*
+ * as_batch_expired returns true if the current batch has expired. A batch
+ * is a set of reads or a set of writes.
+ */
+static inline int as_batch_expired(struct as_data *ad)
+{
+ if (ad->changed_batch)
+ return 0;
+
+ if (ad->batch_data_dir == REQ_SYNC)
+ /* TODO! add a check so a complete fifo gets written? */
+ return time_after(jiffies, ad->current_batch_expires);
+
+ return time_after(jiffies, ad->current_batch_expires)
+ || ad->current_write_count == 0;
+}
+
+/*
+ * move an entry to dispatch queue
+ */
+static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq)
+{
+ const int data_dir = arq->is_sync;
+
+ BUG_ON(!ON_RB(&arq->rb_node));
+
+ as_antic_stop(ad);
+ ad->antic_status = ANTIC_OFF;
+
+ /*
+ * This has to be set in order to be correctly updated by
+ * as_find_next_arq
+ */
+ ad->last_sector[data_dir] = arq->request->sector
+ + arq->request->nr_sectors;
+
+ ad->nr_dispatched++;
+
+ if (data_dir == REQ_SYNC) {
+ /* In case we have to anticipate after this */
+ copy_io_context(&ad->io_context, &arq->io_context);
+ } else {
+ if (ad->io_context) {
+ put_io_context(ad->io_context);
+ ad->io_context = NULL;
+ }
+
+ if (ad->current_write_count != 0)
+ ad->current_write_count--;
+ }
+ ad->ioc_finished = 0;
+
+ ad->next_arq[data_dir] = as_find_next_arq(ad, arq);
+
+ /*
+ * take it off the sort and fifo list, add to dispatch queue
+ */
+ as_remove_queued_request(ad->q, arq->request);
+ list_add_tail(&arq->request->queuelist, ad->dispatch);
+ if (arq->io_context && arq->io_context->aic)
+ atomic_inc(&arq->io_context->aic->nr_dispatched);
+
+ WARN_ON(arq->state != AS_RQ_QUEUED);
+ arq->state = AS_RQ_DISPATCHED;
+}
+
+/*
+ * as_dispatch_request selects the best request according to
+ * read/write expire, batch expire, etc, and moves it to the dispatch
+ * queue. Returns 1 if a request was found, 0 otherwise.
+ */
+static int as_dispatch_request(struct as_data *ad)
+{
+ struct as_rq *arq;
+ const int reads = !list_empty(&ad->fifo_list[REQ_SYNC]);
+ const int writes = !list_empty(&ad->fifo_list[REQ_ASYNC]);
+
+ /* Signal that the write batch was uncontended, so we can't time it */
+ if (ad->batch_data_dir == REQ_ASYNC && !reads) {
+ if (ad->current_write_count == 0 || !writes)
+ ad->write_batch_idled = 1;
+ }
+
+ if (!(reads || writes)
+ || ad->antic_status == ANTIC_WAIT_REQ
+ || ad->antic_status == ANTIC_WAIT_NEXT
+ || ad->changed_batch == 1)
+ return 0;
+
+ if (!(reads && writes && as_batch_expired(ad)) ) {
+ /*
+ * batch is still running or no reads or no writes
+ */
+ arq = ad->next_arq[ad->batch_data_dir];
+
+ if (ad->batch_data_dir == REQ_SYNC && ad->antic_expire) {
+ if (as_fifo_expired(ad, REQ_SYNC))
+ goto fifo_expired;
+
+ if (as_can_anticipate(ad, arq)) {
+ as_antic_waitreq(ad);
+ return 0;
+ }
+ }
+
+ if (arq) {
+ /* we have a "next request" */
+ if (reads && !writes)
+ ad->current_batch_expires =
+ jiffies + ad->batch_expire[REQ_SYNC];
+ goto dispatch_request;
+ }
+ }
+
+ /*
+ * at this point we are not running a batch. select the appropriate
+ * data direction (read / write)
+ */
+
+ if (reads) {
+ BUG_ON(RB_EMPTY(&ad->sort_list[REQ_SYNC]));
+
+ if (writes && ad->batch_data_dir == REQ_SYNC)
+ /*
+ * Last batch was a read, switch to writes
+ */
+ goto dispatch_writes;
+
+ if (ad->batch_data_dir == REQ_ASYNC)
+ ad->changed_batch = 1;
+ ad->batch_data_dir = REQ_SYNC;
+ arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
+ ad->last_check_fifo[ad->batch_data_dir] = jiffies;
+ goto dispatch_request;
+ }
+
+ /*
+ * the last batch was a read
+ */
+
+ if (writes) {
+dispatch_writes:
+ BUG_ON(RB_EMPTY(&ad->sort_list[REQ_ASYNC]));
+
+ if (ad->batch_data_dir == REQ_SYNC)
+ ad->changed_batch = 1;
+ ad->batch_data_dir = REQ_ASYNC;
+ ad->current_write_count = ad->write_batch_count;
+ ad->write_batch_idled = 0;
+ arq = ad->next_arq[ad->batch_data_dir];
+ goto dispatch_request;
+ }
+
+ BUG();
+ return 0;
+
+dispatch_request:
+ /*
+ * If a request has expired, service it.
+ */
+
+ if (as_fifo_expired(ad, ad->batch_data_dir)) {
+fifo_expired:
+ arq = list_entry_fifo(ad->fifo_list[ad->batch_data_dir].next);
+ BUG_ON(arq == NULL);
+ }
+
+ if (ad->changed_batch) {
+ if (ad->changed_batch == 1 && ad->nr_dispatched)
+ return 0;
+ if (ad->batch_data_dir == REQ_ASYNC) {
+ ad->current_batch_expires = jiffies +
+ ad->batch_expire[REQ_ASYNC];
+ ad->changed_batch = 0;
+ } else
+ ad->changed_batch = 2;
+ arq->request->flags |= REQ_HARDBARRIER;
+ }
+
+ /*
+ * arq is the selected appropriate request.
+ */
+ as_move_to_dispatch(ad, arq);
+
+ return 1;
+}
+
+static struct request *as_next_request(request_queue_t *q)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct request *rq = NULL;
+
+ /*
+ * if there are still requests on the dispatch queue, grab the first
+ */
+ if (!list_empty(ad->dispatch) || as_dispatch_request(ad))
+ rq = list_entry_rq(ad->dispatch->next);
+
+ return rq;
+}
+
+/*
+ * add arq to rbtree and fifo
+ */
+static void as_add_request(struct as_data *ad, struct as_rq *arq)
+{
+ int data_dir;
+
+ if (rq_data_dir(arq->request) == READ
+ || current->flags&PF_SYNCWRITE)
+ arq->is_sync = 1;
+ else
+ arq->is_sync = 0;
+ data_dir = arq->is_sync;
+
+ arq->io_context = as_get_io_context();
+
+ if (arq->io_context) {
+ atomic_inc(&arq->io_context->aic->nr_queued);
+ as_update_iohist(arq->io_context->aic, arq->request);
+ }
+
+ as_add_arq_rb(ad, arq);
+
+ /*
+ * set expire time (only used for reads) and add to fifo list
+ */
+ arq->expires = jiffies + ad->fifo_expire[data_dir];
+ list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]);
+ arq->state = AS_RQ_QUEUED;
+ as_update_arq(ad, arq); /* keep state machine up to date */
+}
+
+static void
+as_insert_request(request_queue_t *q, struct request *rq,
+ struct list_head *insert_here)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = RQ_DATA(rq);
+
+ if (unlikely(rq->flags & REQ_HARDBARRIER)) {
+ AS_INVALIDATE_HASH(ad);
+ q->last_merge = NULL;
+
+ while (ad->next_arq[REQ_SYNC])
+ as_move_to_dispatch(ad, ad->next_arq[REQ_SYNC]);
+
+ while (ad->next_arq[REQ_ASYNC])
+ as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]);
+ }
+
+ if (unlikely(!blk_fs_request(rq))) {
+ if (!insert_here)
+ insert_here = ad->dispatch->prev;
+
+ list_add(&rq->queuelist, insert_here);
+
+ /* Stop anticipating - let this request get through */
+ if (!list_empty(ad->dispatch)
+ && (ad->antic_status == ANTIC_WAIT_REQ
+ || ad->antic_status == ANTIC_WAIT_NEXT))
+ as_antic_stop(ad);
+
+ return;
+ }
+
+ if (rq_mergeable(rq)) {
+ as_add_arq_hash(ad, arq);
+
+ if (!q->last_merge)
+ q->last_merge = &rq->queuelist;
+ }
+
+ as_add_request(ad, arq);
+}
+
+/*
+ * as_queue_empty tells us if there are requests left in the device. It may
+ * not be the case that a driver can get the next request even if the queue
+ * is not empty - it is used in the block layer to check for plugging and
+ * merging opportunities
+ */
+static int as_queue_empty(request_queue_t *q)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+
+ if (!list_empty(&ad->fifo_list[REQ_ASYNC])
+ || !list_empty(&ad->fifo_list[REQ_SYNC])
+ || !list_empty(ad->dispatch))
+ return 0;
+
+ return 1;
+}
+
+static struct request *
+as_former_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ struct rb_node *rbprev = rb_prev(&arq->rb_node);
+ struct request *ret = NULL;
+
+ if (rbprev)
+ ret = rb_entry_arq(rbprev)->request;
+
+ return ret;
+}
+
+static struct request *
+as_latter_request(request_queue_t *q, struct request *rq)
+{
+ struct as_rq *arq = RQ_DATA(rq);
+ struct rb_node *rbnext = rb_next(&arq->rb_node);
+ struct request *ret = NULL;
+
+ if (rbnext)
+ ret = rb_entry_arq(rbnext)->request;
+
+ return ret;
+}
+
+static int
+as_merge(request_queue_t *q, struct list_head **insert, struct bio *bio)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ sector_t rb_key = bio->bi_sector + bio_sectors(bio);
+ struct request *__rq;
+ int ret;
+
+ /*
+ * try last_merge to avoid going to hash
+ */
+ ret = elv_try_last_merge(q, bio);
+ if (ret != ELEVATOR_NO_MERGE) {
+ __rq = list_entry_rq(q->last_merge);
+ goto out_insert;
+ }
+
+ /*
+ * see if the merge hash can satisfy a back merge
+ */
+ __rq = as_find_arq_hash(ad, bio->bi_sector);
+ if (__rq) {
+ BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
+
+ if (elv_rq_merge_ok(__rq, bio)) {
+ ret = ELEVATOR_BACK_MERGE;
+ goto out;
+ }
+ }
+
+ /*
+ * check for front merge
+ */
+ __rq = as_find_arq_rb(ad, rb_key, bio_data_dir(bio));
+ if (__rq) {
+ BUG_ON(rb_key != rq_rb_key(__rq));
+
+ if (elv_rq_merge_ok(__rq, bio)) {
+ ret = ELEVATOR_FRONT_MERGE;
+ goto out;
+ }
+ }
+
+ return ELEVATOR_NO_MERGE;
+out:
+ q->last_merge = &__rq->queuelist;
+out_insert:
+ if (ret)
+ as_hot_arq_hash(ad, RQ_DATA(__rq));
+ *insert = &__rq->queuelist;
+ return ret;
+}
+
+static void as_merged_request(request_queue_t *q, struct request *req)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = RQ_DATA(req);
+
+ /*
+ * hash always needs to be repositioned, key is end sector
+ */
+ as_del_arq_hash(arq);
+ as_add_arq_hash(ad, arq);
+
+ /*
+ * if the merge was a front merge, we need to reposition request
+ */
+ if (rq_rb_key(req) != arq->rb_key) {
+ as_del_arq_rb(ad, arq);
+ as_add_arq_rb(ad, arq);
+ /*
+ * Note! At this stage of this and the next function, our next
+ * request may not be optimal - eg the request may have "grown"
+ * behind the disk head. We currently don't bother adjusting.
+ */
+ }
+
+ q->last_merge = &req->queuelist;
+}
+
+static void
+as_merged_requests(request_queue_t *q, struct request *req,
+ struct request *next)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = RQ_DATA(req);
+ struct as_rq *anext = RQ_DATA(next);
+
+ BUG_ON(!arq);
+ BUG_ON(!anext);
+
+ /*
+ * reposition arq (this is the merged request) in hash, and in rbtree
+ * in case of a front merge
+ */
+ as_del_arq_hash(arq);
+ as_add_arq_hash(ad, arq);
+
+ if (rq_rb_key(req) != arq->rb_key) {
+ as_del_arq_rb(ad, arq);
+ as_add_arq_rb(ad, arq);
+ }
+
+ /*
+ * if anext expires before arq, assign its expire time to arq
+ * and move into anext position (anext will be deleted) in fifo
+ */
+ if (!list_empty(&arq->fifo) && !list_empty(&anext->fifo)) {
+ if (time_before(anext->expires, arq->expires)) {
+ list_move(&arq->fifo, &anext->fifo);
+ arq->expires = anext->expires;
+ /*
+ * Don't copy here but swap, because when anext is
+ * removed below, it must contain the unused context
+ */
+ swap_io_context(&arq->io_context, &anext->io_context);
+ }
+ }
+
+ /*
+ * kill knowledge of next, this one is a goner
+ */
+ as_remove_queued_request(q, next);
+ put_io_context(anext->io_context);
+}
+
+/*
+ * This is executed in a "deferred" process context, by kblockd. It calls the
+ * driver's request_fn so the driver can submit that request.
+ *
+ * IMPORTANT! This guy will reenter the elevator, so set up all queue global
+ * state before calling, and don't rely on any state over calls.
+ *
+ * FIXME! dispatch queue is not a queue at all!
+ */
+static void as_work_handler(void *data)
+{
+ struct request_queue *q = data;
+ unsigned long flags;
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ if (as_next_request(q))
+ q->request_fn(q);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+static void as_put_request(request_queue_t *q, struct request *rq)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = RQ_DATA(rq);
+
+ if (!arq) {
+ WARN_ON(1);
+ return;
+ }
+
+ mempool_free(arq, ad->arq_pool);
+ rq->elevator_private = NULL;
+}
+
+static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+{
+ struct as_data *ad = q->elevator.elevator_data;
+ struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
+
+ if (arq) {
+ RB_CLEAR(&arq->rb_node);
+ arq->request = rq;
+ arq->state = AS_RQ_NEW;
+ arq->io_context = NULL;
+ INIT_LIST_HEAD(&arq->hash);
+ arq->hash_valid_count = 0;
+ INIT_LIST_HEAD(&arq->fifo);
+ rq->elevator_private = arq;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int as_may_queue(request_queue_t *q, int rw)
+{
+ int ret = 0;
+ struct as_data *ad = q->elevator.elevator_data;
+ struct io_context *ioc;
+ if (ad->antic_status == ANTIC_WAIT_REQ ||
+ ad->antic_status == ANTIC_WAIT_NEXT) {
+ ioc = as_get_io_context();
+ if (ad->io_context == ioc)
+ ret = 1;
+ put_io_context(ioc);
+ }
+
+ return ret;
+}
+
+static void as_exit(request_queue_t *q, elevator_t *e)
+{
+ struct as_data *ad = e->elevator_data;
+
+ del_timer_sync(&ad->antic_timer);
+ kblockd_flush();
+
+ BUG_ON(!list_empty(&ad->fifo_list[REQ_SYNC]));
+ BUG_ON(!list_empty(&ad->fifo_list[REQ_ASYNC]));
+
+ mempool_destroy(ad->arq_pool);
+ put_io_context(ad->io_context);
+ kfree(ad->hash);
+ kfree(ad);
+}
+
+/*
+ * initialize elevator private data (as_data), and alloc a arq for
+ * each request on the free lists
+ */
+static int as_init(request_queue_t *q, elevator_t *e)
+{
+ struct as_data *ad;
+ int i;
+
+ if (!arq_pool)
+ return -ENOMEM;
+
+ ad = kmalloc(sizeof(*ad), GFP_KERNEL);
+ if (!ad)
+ return -ENOMEM;
+ memset(ad, 0, sizeof(*ad));
+
+ ad->q = q; /* Identify what queue the data belongs to */
+
+ ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL);
+ if (!ad->hash) {
+ kfree(ad);
+ return -ENOMEM;
+ }
+
+ ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool);
+ if (!ad->arq_pool) {
+ kfree(ad->hash);
+ kfree(ad);
+ return -ENOMEM;
+ }
+
+ /* anticipatory scheduling helpers */
+ ad->antic_timer.function = as_antic_timeout;
+ ad->antic_timer.data = (unsigned long)q;
+ init_timer(&ad->antic_timer);
+ INIT_WORK(&ad->antic_work, as_work_handler, q);
+
+ for (i = 0; i < AS_HASH_ENTRIES; i++)
+ INIT_LIST_HEAD(&ad->hash[i]);
+
+ INIT_LIST_HEAD(&ad->fifo_list[REQ_SYNC]);
+ INIT_LIST_HEAD(&ad->fifo_list[REQ_ASYNC]);
+ ad->sort_list[REQ_SYNC] = RB_ROOT;
+ ad->sort_list[REQ_ASYNC] = RB_ROOT;
+ ad->dispatch = &q->queue_head;
+ ad->fifo_expire[REQ_SYNC] = default_read_expire;
+ ad->fifo_expire[REQ_ASYNC] = default_write_expire;
+ ad->hash_valid_count = 1;
+ ad->antic_expire = default_antic_expire;
+ ad->batch_expire[REQ_SYNC] = default_read_batch_expire;
+ ad->batch_expire[REQ_ASYNC] = default_write_batch_expire;
+ e->elevator_data = ad;
+
+ ad->current_batch_expires = jiffies + ad->batch_expire[REQ_SYNC];
+ ad->write_batch_count = ad->batch_expire[REQ_ASYNC] / 10;
+ if (ad->write_batch_count < 2)
+ ad->write_batch_count = 2;
+ return 0;
+}
+
+/*
+ * sysfs parts below
+ */
+struct as_fs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct as_data *, char *);
+ ssize_t (*store)(struct as_data *, const char *, size_t);
+};
+
+static ssize_t
+as_var_show(unsigned int var, char *page)
+{
+ var = (var * 1000) / HZ;
+ return sprintf(page, "%d\n", var);
+}
+
+static ssize_t
+as_var_store(unsigned long *var, const char *page, size_t count)
+{
+ unsigned long tmp;
+ char *p = (char *) page;
+
+ tmp = simple_strtoul(p, &p, 10);
+ if (tmp != 0) {
+ tmp = (tmp * HZ) / 1000;
+ if (tmp == 0)
+ tmp = 1;
+ }
+ *var = tmp;
+ return count;
+}
+
+#define SHOW_FUNCTION(__FUNC, __VAR) \
+static ssize_t __FUNC(struct as_data *ad, char *page) \
+{ \
+ return as_var_show(__VAR, (page)); \
+}
+SHOW_FUNCTION(as_readexpire_show, ad->fifo_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_writeexpire_show, ad->fifo_expire[REQ_ASYNC]);
+SHOW_FUNCTION(as_anticexpire_show, ad->antic_expire);
+SHOW_FUNCTION(as_read_batchexpire_show, ad->batch_expire[REQ_SYNC]);
+SHOW_FUNCTION(as_write_batchexpire_show, ad->batch_expire[REQ_ASYNC]);
+#undef SHOW_FUNCTION
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \
+static ssize_t __FUNC(struct as_data *ad, const char *page, size_t count) \
+{ \
+ int ret = as_var_store(__PTR, (page), count); \
+ if (*(__PTR) < (MIN)) \
+ *(__PTR) = (MIN); \
+ else if (*(__PTR) > (MAX)) \
+ *(__PTR) = (MAX); \
+ return ret; \
+}
+STORE_FUNCTION(as_readexpire_store, &ad->fifo_expire[REQ_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_writeexpire_store, &ad->fifo_expire[REQ_ASYNC], 0, INT_MAX);
+STORE_FUNCTION(as_anticexpire_store, &ad->antic_expire, 0, INT_MAX);
+STORE_FUNCTION(as_read_batchexpire_store,
+ &ad->batch_expire[REQ_SYNC], 0, INT_MAX);
+STORE_FUNCTION(as_write_batchexpire_store,
+ &ad->batch_expire[REQ_ASYNC], 0, INT_MAX);
+#undef STORE_FUNCTION
+
+static struct as_fs_entry as_readexpire_entry = {
+ .attr = {.name = "read_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = as_readexpire_show,
+ .store = as_readexpire_store,
+};
+static struct as_fs_entry as_writeexpire_entry = {
+ .attr = {.name = "write_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = as_writeexpire_show,
+ .store = as_writeexpire_store,
+};
+static struct as_fs_entry as_anticexpire_entry = {
+ .attr = {.name = "antic_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = as_anticexpire_show,
+ .store = as_anticexpire_store,
+};
+static struct as_fs_entry as_read_batchexpire_entry = {
+ .attr = {.name = "read_batch_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = as_read_batchexpire_show,
+ .store = as_read_batchexpire_store,
+};
+static struct as_fs_entry as_write_batchexpire_entry = {
+ .attr = {.name = "write_batch_expire", .mode = S_IRUGO | S_IWUSR },
+ .show = as_write_batchexpire_show,
+ .store = as_write_batchexpire_store,
+};
+
+static struct attribute *default_attrs[] = {
+ &as_readexpire_entry.attr,
+ &as_writeexpire_entry.attr,
+ &as_anticexpire_entry.attr,
+ &as_read_batchexpire_entry.attr,
+ &as_write_batchexpire_entry.attr,
+ NULL,
+};
+
+#define to_as(atr) container_of((atr), struct as_fs_entry, attr)
+
+static ssize_t
+as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+ elevator_t *e = container_of(kobj, elevator_t, kobj);
+ struct as_fs_entry *entry = to_as(attr);
+
+ if (!entry->show)
+ return 0;
+
+ return entry->show(e->elevator_data, page);
+}
+
+static ssize_t
+as_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *page, size_t length)
+{
+ elevator_t *e = container_of(kobj, elevator_t, kobj);
+ struct as_fs_entry *entry = to_as(attr);
+
+ if (!entry->store)
+ return -EINVAL;
+
+ return entry->store(e->elevator_data, page, length);
+}
+
+static struct sysfs_ops as_sysfs_ops = {
+ .show = as_attr_show,
+ .store = as_attr_store,
+};
+
+struct kobj_type as_ktype = {
+ .sysfs_ops = &as_sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+static int __init as_slab_setup(void)
+{
+ arq_pool = kmem_cache_create("as_arq", sizeof(struct as_rq),
+ 0, 0, NULL, NULL);
+
+ if (!arq_pool)
+ panic("as: can't init slab pool\n");
+
+ return 0;
+}
+
+subsys_initcall(as_slab_setup);
+
+elevator_t iosched_as = {
+ .elevator_merge_fn = as_merge,
+ .elevator_merged_fn = as_merged_request,
+ .elevator_merge_req_fn = as_merged_requests,
+ .elevator_next_req_fn = as_next_request,
+ .elevator_add_req_fn = as_insert_request,
+ .elevator_remove_req_fn = as_remove_request,
+ .elevator_queue_empty_fn = as_queue_empty,
+ .elevator_completed_req_fn = as_completed_request,
+ .elevator_former_req_fn = as_former_request,
+ .elevator_latter_req_fn = as_latter_request,
+ .elevator_set_req_fn = as_set_request,
+ .elevator_put_req_fn = as_put_request,
+ .elevator_may_queue_fn = as_may_queue,
+ .elevator_init_fn = as_init,
+ .elevator_exit_fn = as_exit,
+
+ .elevator_ktype = &as_ktype,
+};
+
+EXPORT_SYMBOL(iosched_as);
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 2933c96a6142..03165688cccd 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1887,7 +1887,7 @@ queue:
BUG();
if (( c = cmd_alloc(h, 1)) == NULL)
- goto startio;
+ goto full;
blkdev_dequeue_request(creq);
@@ -1960,8 +1960,9 @@ queue:
h->maxQsinceinit = h->Qdepth;
goto queue;
-startio:
+full:
blk_stop_queue(q);
+startio:
start_io(h);
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 00b56d022b0e..485561a037fc 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -361,17 +361,31 @@ void elv_put_request(request_queue_t *q, struct request *rq)
e->elevator_put_req_fn(q, rq);
}
-int elv_register_queue(struct gendisk *disk)
+int elv_may_queue(request_queue_t *q, int rw)
{
- request_queue_t *q = disk->queue;
- elevator_t *e;
+ elevator_t *e = &q->elevator;
+
+ if (e->elevator_may_queue_fn)
+ return e->elevator_may_queue_fn(q, rw);
+
+ return 0;
+}
+
+void elv_completed_request(request_queue_t *q, struct request *rq)
+{
+ elevator_t *e = &q->elevator;
- if (!q)
- return -ENXIO;
+ if (e->elevator_completed_req_fn)
+ e->elevator_completed_req_fn(q, rq);
+}
+
+int elv_register_queue(struct request_queue *q)
+{
+ elevator_t *e;
e = &q->elevator;
- e->kobj.parent = kobject_get(&disk->kobj);
+ e->kobj.parent = kobject_get(&q->kobj);
if (!e->kobj.parent)
return -EBUSY;
@@ -381,14 +395,12 @@ int elv_register_queue(struct gendisk *disk)
return kobject_register(&e->kobj);
}
-void elv_unregister_queue(struct gendisk *disk)
+void elv_unregister_queue(struct request_queue *q)
{
- request_queue_t *q = disk->queue;
-
if (q) {
elevator_t * e = &q->elevator;
kobject_unregister(&e->kobj);
- kobject_put(&disk->kobj);
+ kobject_put(&q->kobj);
}
}
@@ -408,5 +420,6 @@ EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_next_request);
EXPORT_SYMBOL(elv_remove_request);
EXPORT_SYMBOL(elv_queue_empty);
+EXPORT_SYMBOL(elv_completed_request);
EXPORT_SYMBOL(elevator_exit);
EXPORT_SYMBOL(elevator_init);
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ca2332522f9a..40ff4c76558b 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -3767,7 +3767,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
* Needed so that programs such as fdrawcmd still can work on write
* protected disks */
if ((filp->f_mode & 2) ||
- (inode->i_sb && (permission(inode,2) == 0)))
+ (inode->i_sb && (permission(inode,2, NULL) == 0)))
filp->private_data = (void*) 8;
if (UFDCS->rawcmd == 1)
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 889b8753c29f..361aee8ab255 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -191,7 +191,7 @@ void add_disk(struct gendisk *disk)
blk_register_region(MKDEV(disk->major, disk->first_minor),
disk->minors, NULL, exact_match, exact_lock, disk);
register_disk(disk);
- elv_register_queue(disk);
+ blk_register_queue(disk);
}
EXPORT_SYMBOL(add_disk);
@@ -199,7 +199,7 @@ EXPORT_SYMBOL(del_gendisk); /* in partitions/check.c */
void unlink_gendisk(struct gendisk *disk)
{
- elv_unregister_queue(disk);
+ blk_unregister_queue(disk);
blk_unregister_region(MKDEV(disk->major, disk->first_minor),
disk->minors);
}
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 6287b0064d9b..f03a77be82b6 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -42,40 +42,50 @@ static kmem_cache_t *request_cachep;
static LIST_HEAD(blk_plug_list);
static spinlock_t blk_plug_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
+static wait_queue_head_t congestion_wqh[2];
+
/*
- * Number of requests per queue. This many for reads and for writes (twice
- * this number, total).
+ * Controlling structure to kblockd
*/
-static int queue_nr_requests;
+static struct workqueue_struct *kblockd_workqueue;
unsigned long blk_max_low_pfn, blk_max_pfn;
-static wait_queue_head_t congestion_wqh[2];
+
+/* Amount of time in which a process may batch requests */
+#define BLK_BATCH_TIME (HZ/50UL)
+
+/* Number of requests a "batching" process may submit */
+#define BLK_BATCH_REQ 32
/*
- * Return the threshold (number of free requests) at which the queue is
+ * Return the threshold (number of used requests) at which the queue is
* considered to be congested. It include a little hysteresis to keep the
* context switch rate down.
*/
-static inline int queue_congestion_on_threshold(void)
+static inline int queue_congestion_on_threshold(struct request_queue *q)
{
int ret;
- ret = queue_nr_requests / 8 - 1;
- if (ret < 0)
- ret = 1;
+ ret = q->nr_requests - (q->nr_requests / 8) + 1;
+
+ if (ret > q->nr_requests)
+ ret = q->nr_requests;
+
return ret;
}
/*
* The threshold at which a queue is considered to be uncongested
*/
-static inline int queue_congestion_off_threshold(void)
+static inline int queue_congestion_off_threshold(struct request_queue *q)
{
int ret;
- ret = queue_nr_requests / 8 + 1;
- if (ret > queue_nr_requests)
- ret = queue_nr_requests;
+ ret = q->nr_requests - (q->nr_requests / 8) - 1;
+
+ if (ret < 1)
+ ret = 1;
+
return ret;
}
@@ -188,6 +198,7 @@ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn)
/*
* set defaults
*/
+ q->nr_requests = BLKDEV_MAX_RQ;
q->max_phys_segments = MAX_PHYS_SEGMENTS;
q->max_hw_segments = MAX_HW_SEGMENTS;
q->make_request_fn = mfn;
@@ -441,13 +452,15 @@ void blk_queue_free_tags(request_queue_t *q)
q->queue_flags &= ~(1 << QUEUE_FLAG_QUEUED);
}
-static int init_tag_map(struct blk_queue_tag *tags, int depth)
+static int
+init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
{
int bits, i;
- if (depth > (queue_nr_requests*2)) {
- depth = (queue_nr_requests*2);
- printk(KERN_ERR "%s: adjusted depth to %d\n", __FUNCTION__, depth);
+ if (depth > q->nr_requests * 2) {
+ depth = q->nr_requests * 2;
+ printk(KERN_ERR "%s: adjusted depth to %d\n",
+ __FUNCTION__, depth);
}
tags->tag_index = kmalloc(depth * sizeof(struct request *), GFP_ATOMIC);
@@ -476,7 +489,6 @@ fail:
return -ENOMEM;
}
-
/**
* blk_queue_init_tags - initialize the queue tag info
* @q: the request queue for the device
@@ -490,7 +502,7 @@ int blk_queue_init_tags(request_queue_t *q, int depth)
if (!tags)
goto fail;
- if (init_tag_map(tags, depth))
+ if (init_tag_map(q, tags, depth))
goto fail;
INIT_LIST_HEAD(&tags->busy_list);
@@ -540,7 +552,7 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
tag_map = bqt->tag_map;
max_depth = bqt->real_max_depth;
- if (init_tag_map(bqt, new_depth))
+ if (init_tag_map(q, bqt, new_depth))
return -ENOMEM;
memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
@@ -1022,7 +1034,7 @@ static inline void __generic_unplug_device(request_queue_t *q)
/*
* was plugged, fire request_fn if queue has stuff to do
*/
- if (!elv_queue_empty(q))
+ if (elv_next_request(q))
q->request_fn(q);
}
@@ -1057,7 +1069,7 @@ static void blk_unplug_timeout(unsigned long data)
{
request_queue_t *q = (request_queue_t *)data;
- schedule_work(&q->unplug_work);
+ kblockd_schedule_work(&q->unplug_work);
}
/**
@@ -1072,8 +1084,8 @@ static void blk_unplug_timeout(unsigned long data)
**/
void blk_start_queue(request_queue_t *q)
{
- if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
- schedule_work(&q->unplug_work);
+ clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags);
+ schedule_work(&q->unplug_work);
}
/**
@@ -1165,7 +1177,7 @@ void blk_cleanup_queue(request_queue_t * q)
elevator_exit(q);
del_timer_sync(&q->unplug_timer);
- flush_scheduled_work();
+ kblockd_flush();
mempool_destroy(rl->rq_pool);
@@ -1180,6 +1192,8 @@ static int blk_init_free_list(request_queue_t *q)
struct request_list *rl = &q->rq;
rl->count[READ] = rl->count[WRITE] = 0;
+ init_waitqueue_head(&rl->wait[READ]);
+ init_waitqueue_head(&rl->wait[WRITE]);
rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
@@ -1191,6 +1205,18 @@ static int blk_init_free_list(request_queue_t *q)
static int __make_request(request_queue_t *, struct bio *);
+static elevator_t *chosen_elevator = &iosched_as;
+
+static int __init elevator_setup(char *str)
+{
+ if (!strcmp(str, "deadline"))
+ chosen_elevator = &iosched_deadline;
+ if (!strcmp(str, "as"))
+ chosen_elevator = &iosched_as;
+ return 1;
+}
+__setup("elevator=", elevator_setup);
+
/**
* blk_init_queue - prepare a request queue for use with a block device
* @q: The &request_queue_t to be initialised
@@ -1222,11 +1248,20 @@ static int __make_request(request_queue_t *, struct bio *);
int blk_init_queue(request_queue_t *q, request_fn_proc *rfn, spinlock_t *lock)
{
int ret;
+ static int printed;
if (blk_init_free_list(q))
return -ENOMEM;
- if ((ret = elevator_init(q, &iosched_deadline))) {
+ if (!printed) {
+ printed = 1;
+ if (chosen_elevator == &iosched_deadline)
+ printk("deadline elevator\n");
+ else if (chosen_elevator == &iosched_as)
+ printk("anticipatory scheduling elevator\n");
+ }
+
+ if ((ret = elevator_init(q, chosen_elevator))) {
blk_cleanup_queue(q);
return ret;
}
@@ -1271,6 +1306,60 @@ static inline struct request *blk_alloc_request(request_queue_t *q,int gfp_mask)
return NULL;
}
+/*
+ * ioc_batching returns true if the ioc is a valid batching request and
+ * should be given priority access to a request.
+ */
+static inline int ioc_batching(struct io_context *ioc)
+{
+ if (!ioc)
+ return 0;
+
+ /*
+ * Make sure the process is able to allocate at least 1 request
+ * even if the batch times out, otherwise we could theoretically
+ * lose wakeups.
+ */
+ return ioc->nr_batch_requests == BLK_BATCH_REQ ||
+ (ioc->nr_batch_requests > 0
+ && time_before(jiffies, ioc->last_waited + BLK_BATCH_TIME));
+}
+
+/*
+ * ioc_set_batching sets ioc to be a new "batcher" if it is not one. This
+ * will cause the process to be a "batcher" on all queues in the system. This
+ * is the behaviour we want though - once it gets a wakeup it should be given
+ * a nice run.
+ */
+void ioc_set_batching(struct io_context *ioc)
+{
+ if (!ioc || ioc_batching(ioc))
+ return;
+
+ ioc->nr_batch_requests = BLK_BATCH_REQ;
+ ioc->last_waited = jiffies;
+}
+
+/*
+ * A request has just been released. Account for it, update the full and
+ * congestion status, wake up any waiters. Called under q->queue_lock.
+ */
+static void freed_request(request_queue_t *q, int rw)
+{
+ struct request_list *rl = &q->rq;
+
+ rl->count[rw]--;
+ if (rl->count[rw] < queue_congestion_off_threshold(q))
+ clear_queue_congested(q, rw);
+ if (rl->count[rw]+1 <= q->nr_requests) {
+ smp_mb();
+ if (waitqueue_active(&rl->wait[rw]))
+ wake_up(&rl->wait[rw]);
+ if (!waitqueue_active(&rl->wait[rw]))
+ blk_clear_queue_full(q, rw);
+ }
+}
+
#define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist)
/*
* Get a free request, queue_lock must not be held
@@ -1279,26 +1368,54 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
{
struct request *rq = NULL;
struct request_list *rl = &q->rq;
+ struct io_context *ioc = get_io_context(gfp_mask);
spin_lock_irq(q->queue_lock);
- if (rl->count[rw] == BLKDEV_MAX_RQ) {
+ if (rl->count[rw]+1 >= q->nr_requests) {
+ /*
+ * The queue will fill after this allocation, so set it as
+ * full, and mark this process as "batching". This process
+ * will be allowed to complete a batch of requests, others
+ * will be blocked.
+ */
+ if (!blk_queue_full(q, rw)) {
+ ioc_set_batching(ioc);
+ blk_set_queue_full(q, rw);
+ }
+ }
+
+ if (blk_queue_full(q, rw)
+ && !ioc_batching(ioc) && !elv_may_queue(q, rw)) {
+ /*
+ * The queue is full and the allocating process is not a
+ * "batcher", and not exempted by the IO scheduler
+ */
spin_unlock_irq(q->queue_lock);
goto out;
}
+
rl->count[rw]++;
- if ((BLKDEV_MAX_RQ - rl->count[rw]) < queue_congestion_on_threshold())
+ if (rl->count[rw] >= queue_congestion_on_threshold(q))
set_queue_congested(q, rw);
spin_unlock_irq(q->queue_lock);
rq = blk_alloc_request(q, gfp_mask);
if (!rq) {
+ /*
+ * Allocation failed presumably due to memory. Undo anything
+ * we might have messed up.
+ *
+ * Allocating task should really be put onto the front of the
+ * wait queue, but this is pretty rare.
+ */
spin_lock_irq(q->queue_lock);
- rl->count[rw]--;
- if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold())
- clear_queue_congested(q, rw);
+ freed_request(q, rw);
spin_unlock_irq(q->queue_lock);
goto out;
}
+
+ if (ioc_batching(ioc))
+ ioc->nr_batch_requests--;
INIT_LIST_HEAD(&rq->queuelist);
@@ -1321,22 +1438,44 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
rq->sense = NULL;
out:
+ put_io_context(ioc);
return rq;
}
/*
- * No available requests for this queue, unplug the device.
+ * No available requests for this queue, unplug the device and wait for some
+ * requests to become available.
*/
static struct request *get_request_wait(request_queue_t *q, int rw)
{
+ DEFINE_WAIT(wait);
struct request *rq;
generic_unplug_device(q);
do {
+ struct request_list *rl = &q->rq;
+
+ prepare_to_wait_exclusive(&rl->wait[rw], &wait,
+ TASK_UNINTERRUPTIBLE);
+
rq = get_request(q, rw, GFP_NOIO);
- if (!rq)
- blk_congestion_wait(rw, HZ / 50);
+ if (!rq) {
+ struct io_context *ioc;
+
+ io_schedule();
+
+ /*
+ * After sleeping, we become a "batching" process and
+ * will be able to allocate at least one request, and
+ * up to a big batch of them for a small period time.
+ * See ioc_batching, ioc_set_batching
+ */
+ ioc = get_io_context(GFP_NOIO);
+ ioc_set_batching(ioc);
+ put_io_context(ioc);
+ }
+ finish_wait(&rl->wait[rw], &wait);
} while (!rq);
return rq;
@@ -1348,10 +1487,10 @@ struct request *blk_get_request(request_queue_t *q, int rw, int gfp_mask)
BUG_ON(rw != READ && rw != WRITE);
- rq = get_request(q, rw, gfp_mask);
-
- if (!rq && (gfp_mask & __GFP_WAIT))
+ if (gfp_mask & __GFP_WAIT)
rq = get_request_wait(q, rw);
+ else
+ rq = get_request(q, rw, gfp_mask);
return rq;
}
@@ -1482,6 +1621,8 @@ void __blk_put_request(request_queue_t *q, struct request *req)
if (unlikely(--req->ref_count))
return;
+ elv_completed_request(req->q, req);
+
req->rq_status = RQ_INACTIVE;
req->q = NULL;
req->rl = NULL;
@@ -1496,10 +1637,7 @@ void __blk_put_request(request_queue_t *q, struct request *req)
BUG_ON(!list_empty(&req->queuelist));
blk_free_request(q, req);
-
- rl->count[rw]--;
- if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold())
- clear_queue_congested(q, rw);
+ freed_request(q, rw);
}
}
@@ -1786,13 +1924,12 @@ out:
__blk_put_request(q, freereq);
if (blk_queue_plugged(q)) {
- int nr_queued = q->rq.count[0] + q->rq.count[1];
+ int nr_queued = q->rq.count[READ] + q->rq.count[WRITE];
if (nr_queued == q->unplug_thresh)
__generic_unplug_device(q);
}
spin_unlock_irq(q->queue_lock);
-
return 0;
end_io:
@@ -1800,7 +1937,6 @@ end_io:
return 0;
}
-
/*
* If bio->bi_dev is a partition, remap the location
*/
@@ -1850,8 +1986,7 @@ static inline void blk_partition_remap(struct bio *bio)
* bio happens to be merged with someone else, and may change bi_dev and
* bi_sector for remaps as it sees fit. So the values of these fields
* should NOT be depended on after the call to generic_make_request.
- *
- * */
+ */
void generic_make_request(struct bio *bio)
{
request_queue_t *q;
@@ -2282,31 +2417,287 @@ void blk_rq_prep_restart(struct request *rq)
rq->current_nr_sectors = rq->hard_cur_sectors;
}
+int kblockd_schedule_work(struct work_struct *work)
+{
+ return queue_work(kblockd_workqueue, work);
+}
+
+void kblockd_flush(void)
+{
+ flush_workqueue(kblockd_workqueue);
+}
+
int __init blk_dev_init(void)
{
int i;
+ kblockd_workqueue = create_workqueue("kblockd");
+ if (!kblockd_workqueue)
+ panic("Failed to create kblockd\n");
+
request_cachep = kmem_cache_create("blkdev_requests",
sizeof(struct request), 0, 0, NULL, NULL);
if (!request_cachep)
panic("Can't create request pool slab cache\n");
- queue_nr_requests = BLKDEV_MAX_RQ;
-
- printk("block request queues:\n");
- printk(" %d/%d requests per read queue\n", BLKDEV_MIN_RQ, queue_nr_requests);
- printk(" %d/%d requests per write queue\n", BLKDEV_MIN_RQ, queue_nr_requests);
- printk(" enter congestion at %d\n", queue_congestion_on_threshold());
- printk(" exit congestion at %d\n", queue_congestion_off_threshold());
-
blk_max_low_pfn = max_low_pfn;
blk_max_pfn = max_pfn;
for (i = 0; i < ARRAY_SIZE(congestion_wqh); i++)
init_waitqueue_head(&congestion_wqh[i]);
return 0;
+}
+
+static atomic_t nr_io_contexts = ATOMIC_INIT(0);
+
+/*
+ * IO Context helper functions
+ */
+void put_io_context(struct io_context *ioc)
+{
+ if (ioc == NULL)
+ return;
+
+ BUG_ON(atomic_read(&ioc->refcount) == 0);
+
+ if (atomic_dec_and_test(&ioc->refcount)) {
+ if (ioc->aic && ioc->aic->dtor)
+ ioc->aic->dtor(ioc->aic);
+ kfree(ioc);
+ atomic_dec(&nr_io_contexts);
+ }
+}
+
+/* Called by the exitting task */
+void exit_io_context(void)
+{
+ unsigned long flags;
+ struct io_context *ioc;
+
+ local_irq_save(flags);
+ ioc = current->io_context;
+ if (ioc) {
+ if (ioc->aic && ioc->aic->exit)
+ ioc->aic->exit(ioc->aic);
+ put_io_context(ioc);
+ current->io_context = NULL;
+ } else
+ WARN_ON(1);
+ local_irq_restore(flags);
+}
+
+/*
+ * If the current task has no IO context then create one and initialise it.
+ * If it does have a context, take a ref on it.
+ *
+ * This is always called in the context of the task which submitted the I/O.
+ * But weird things happen, so we disable local interrupts to ensure exclusive
+ * access to *current.
+ */
+struct io_context *get_io_context(int gfp_flags)
+{
+ struct task_struct *tsk = current;
+ unsigned long flags;
+ struct io_context *ret;
+
+ local_irq_save(flags);
+ ret = tsk->io_context;
+ if (ret == NULL) {
+ ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
+ if (ret) {
+ atomic_inc(&nr_io_contexts);
+ atomic_set(&ret->refcount, 1);
+ ret->pid = tsk->pid;
+ ret->last_waited = jiffies; /* doesn't matter... */
+ ret->nr_batch_requests = 0; /* because this is 0 */
+ ret->aic = NULL;
+ tsk->io_context = ret;
+ }
+ }
+ if (ret)
+ atomic_inc(&ret->refcount);
+ local_irq_restore(flags);
+ return ret;
+}
+
+void copy_io_context(struct io_context **pdst, struct io_context **psrc)
+{
+ struct io_context *src = *psrc;
+ struct io_context *dst = *pdst;
+
+ if (src) {
+ BUG_ON(atomic_read(&src->refcount) == 0);
+ atomic_inc(&src->refcount);
+ put_io_context(dst);
+ *pdst = src;
+ }
+}
+
+void swap_io_context(struct io_context **ioc1, struct io_context **ioc2)
+{
+ struct io_context *temp;
+ temp = *ioc1;
+ *ioc1 = *ioc2;
+ *ioc2 = temp;
+}
+
+
+/*
+ * sysfs parts below
+ */
+struct queue_sysfs_entry {
+ struct attribute attr;
+ ssize_t (*show)(struct request_queue *, char *);
+ ssize_t (*store)(struct request_queue *, const char *, size_t);
+};
+
+static ssize_t
+queue_var_show(unsigned int var, char *page)
+{
+ return sprintf(page, "%d\n", var);
+}
+
+static ssize_t
+queue_var_store(unsigned long *var, const char *page, size_t count)
+{
+ char *p = (char *) page;
+
+ *var = simple_strtoul(p, &p, 10);
+ return count;
+}
+
+static ssize_t queue_requests_show(struct request_queue *q, char *page)
+{
+ return queue_var_show(q->nr_requests, (page));
+}
+
+static ssize_t
+queue_requests_store(struct request_queue *q, const char *page, size_t count)
+{
+ struct request_list *rl = &q->rq;
+
+ int ret = queue_var_store(&q->nr_requests, page, count);
+ if (q->nr_requests < BLKDEV_MIN_RQ)
+ q->nr_requests = BLKDEV_MIN_RQ;
+
+ if (rl->count[READ] >= queue_congestion_on_threshold(q))
+ set_queue_congested(q, READ);
+ else if (rl->count[READ] < queue_congestion_off_threshold(q))
+ clear_queue_congested(q, READ);
+
+ if (rl->count[WRITE] >= queue_congestion_on_threshold(q))
+ set_queue_congested(q, WRITE);
+ else if (rl->count[WRITE] < queue_congestion_off_threshold(q))
+ clear_queue_congested(q, WRITE);
+
+ if (rl->count[READ] >= q->nr_requests) {
+ blk_set_queue_full(q, READ);
+ } else if (rl->count[READ]+1 <= q->nr_requests) {
+ blk_clear_queue_full(q, READ);
+ wake_up(&rl->wait[READ]);
+ }
+
+ if (rl->count[WRITE] >= q->nr_requests) {
+ blk_set_queue_full(q, WRITE);
+ } else if (rl->count[WRITE]+1 <= q->nr_requests) {
+ blk_clear_queue_full(q, WRITE);
+ wake_up(&rl->wait[WRITE]);
+ }
+ return ret;
+}
+
+static struct queue_sysfs_entry queue_requests_entry = {
+ .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
+ .show = queue_requests_show,
+ .store = queue_requests_store,
};
+static struct attribute *default_attrs[] = {
+ &queue_requests_entry.attr,
+ NULL,
+};
+
+#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
+
+static ssize_t
+queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+{
+ struct queue_sysfs_entry *entry = to_queue(attr);
+ struct request_queue *q;
+
+ q = container_of(kobj, struct request_queue, kobj);
+ if (!entry->show)
+ return 0;
+
+ return entry->show(q, page);
+}
+
+static ssize_t
+queue_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *page, size_t length)
+{
+ struct queue_sysfs_entry *entry = to_queue(attr);
+ struct request_queue *q;
+
+ q = container_of(kobj, struct request_queue, kobj);
+ if (!entry->store)
+ return -EINVAL;
+
+ return entry->store(q, page, length);
+}
+
+static struct sysfs_ops queue_sysfs_ops = {
+ .show = queue_attr_show,
+ .store = queue_attr_store,
+};
+
+struct kobj_type queue_ktype = {
+ .sysfs_ops = &queue_sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+int blk_register_queue(struct gendisk *disk)
+{
+ int ret;
+
+ request_queue_t *q = disk->queue;
+
+ if (!q)
+ return -ENXIO;
+
+ q->kobj.parent = kobject_get(&disk->kobj);
+ if (!q->kobj.parent)
+ return -EBUSY;
+
+ snprintf(q->kobj.name, KOBJ_NAME_LEN, "%s", "queue");
+ q->kobj.ktype = &queue_ktype;
+
+ ret = kobject_register(&q->kobj);
+ if (ret < 0)
+ return ret;
+
+ ret = elv_register_queue(q);
+ if (ret) {
+ kobject_unregister(&q->kobj);
+ return ret;
+ }
+
+ return 0;
+}
+
+void blk_unregister_queue(struct gendisk *disk)
+{
+ request_queue_t *q = disk->queue;
+
+ if (q) {
+ elv_unregister_queue(q);
+
+ kobject_unregister(&q->kobj);
+ kobject_put(&disk->kobj);
+ }
+}
+
+
EXPORT_SYMBOL(process_that_request_first);
EXPORT_SYMBOL(end_that_request_first);
EXPORT_SYMBOL(end_that_request_chunk);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 115a16feb0d1..980c1b7dc8ec 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/pcmcia/synclink_cs.c
*
- * $Id: synclink_cs.c,v 4.10 2003/05/13 16:06:03 paulkf Exp $
+ * $Id: synclink_cs.c,v 4.13 2003/06/18 15:29:32 paulkf Exp $
*
* Device driver for Microgate SyncLink PC Card
* multiprotocol serial adapter.
@@ -467,7 +467,6 @@ static int break_on_load=0;
* assigned major number. May be forced as module parameter.
*/
static int ttymajor=0;
-static int cuamajor=0;
static int debug_level = 0;
static int maxframe[MAX_DEVICE_COUNT] = {0,};
@@ -485,7 +484,6 @@ MODULE_PARM(irq_list, "1-4i");
MODULE_PARM(break_on_load,"i");
MODULE_PARM(ttymajor,"i");
-MODULE_PARM(cuamajor,"i");
MODULE_PARM(debug_level,"i");
MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
@@ -493,7 +491,7 @@ MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i");
MODULE_LICENSE("GPL");
static char *driver_name = "SyncLink PC Card driver";
-static char *driver_version = "$Revision: 4.10 $";
+static char *driver_version = "$Revision: 4.13 $";
static struct tty_driver *serial_driver;
@@ -1290,7 +1288,7 @@ void dcd_change(MGSLPC_INFO *info)
(info->serial_signals & SerialSignal_DCD) ? "on" : "off");
if (info->serial_signals & SerialSignal_DCD)
wake_up_interruptible(&info->open_wait);
- else if (!(info->flags & ASYNC_CALLOUT_NOHUP)) {
+ else {
if (debug_level >= DEBUG_LEVEL_ISR)
printk("doing serial hangup...");
if (info->tty)
@@ -2538,14 +2536,17 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
- if (!info || mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
+ if (mgslpc_paranoia_check(info, tty->name, "mgslpc_close"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_close(%s) entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->count);
- if (!info->count || tty_hung_up_p(filp))
+ if (!info->count)
+ return;
+
+ if (tty_hung_up_p(filp))
goto cleanup;
if ((tty->count == 1) && (info->count != 1)) {
@@ -2822,16 +2823,11 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
info = mgslpc_device_list;
while(info && info->line != line)
info = info->next_device;
- if ( !info ){
- printk("%s(%d):Can't find specified device on open (line=%d)\n",
- __FILE__,__LINE__,line);
+ if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
return -ENODEV;
- }
tty->driver_data = info;
info->tty = tty;
- if (mgslpc_paranoia_check(info, tty->name, "mgslpc_open"))
- return -ENODEV;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_open(%s), old ref count = %d\n",
@@ -2879,6 +2875,8 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp)
cleanup:
if (retval) {
+ if (tty->count == 1)
+ info->tty = 0; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index b68901640a19..ccb3804e4977 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/char/synclink.c
*
- * $Id: synclink.c,v 4.9 2003/05/06 21:18:51 paulkf Exp $
+ * $Id: synclink.c,v 4.12 2003/06/18 15:29:32 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
* high speed multiprotocol serial adapters.
@@ -910,7 +910,7 @@ MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.9 $";
+static char *driver_version = "$Revision: 4.12 $";
static int synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent);
@@ -3170,14 +3170,17 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
{
struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
- if (!info || mgsl_paranoia_check(info, tty->name, "mgsl_close"))
+ if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->count);
- if (!info->count || tty_hung_up_p(filp))
+ if (!info->count)
+ return;
+
+ if (tty_hung_up_p(filp))
goto cleanup;
if ((tty->count == 1) && (info->count != 1)) {
@@ -3493,16 +3496,11 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
info = mgsl_device_list;
while(info && info->line != line)
info = info->next_device;
- if ( !info ){
- printk("%s(%d):Can't find specified device on open (line=%d)\n",
- __FILE__,__LINE__,line);
+ if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
return -ENODEV;
- }
tty->driver_data = info;
info->tty = tty;
- if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
- return -ENODEV;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
@@ -3562,6 +3560,8 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp)
cleanup:
if (retval) {
+ if (tty->count == 1)
+ info->tty = 0; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
@@ -4461,7 +4461,6 @@ static struct tty_operations mgsl_ops = {
int mgsl_init_tty(void);
int mgsl_init_tty()
{
- struct mgsl_struct *info;
serial_driver = alloc_tty_driver(mgsl_device_count);
if (!serial_driver)
return -ENOMEM;
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 99e5a937be51..46c23f3f1e68 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1,5 +1,5 @@
/*
- * $Id: synclinkmp.c,v 4.8 2003/04/21 17:46:55 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.12 2003/06/18 15:29:33 paulkf Exp $
*
* Device driver for Microgate SyncLink Multiport
* high speed multiprotocol serial adapter.
@@ -481,7 +481,6 @@ static int break_on_load=0;
* assigned major number. May be forced as module parameter.
*/
static int ttymajor=0;
-static int cuamajor=0;
/*
* Array of user specified options for ISA adapters.
@@ -492,13 +491,12 @@ static int dosyncppp[MAX_DEVICES] = {0,};
MODULE_PARM(break_on_load,"i");
MODULE_PARM(ttymajor,"i");
-MODULE_PARM(cuamajor,"i");
MODULE_PARM(debug_level,"i");
MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICES) "i");
MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICES) "i");
static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.8 $";
+static char *driver_version = "$Revision: 4.12 $";
static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -739,12 +737,8 @@ static int open(struct tty_struct *tty, struct file *filp)
info = synclinkmp_device_list;
while(info && info->line != line)
info = info->next_device;
- if ( !info ){
- printk("%s(%d):%s Can't find specified device on open (line=%d)\n",
- __FILE__,__LINE__,info->device_name,line);
+ if (sanity_check(info, tty->name, "open"))
return -ENODEV;
- }
-
if ( info->init_error ) {
printk("%s(%d):%s device is not allocated, init error=%d\n",
__FILE__,__LINE__,info->device_name,info->init_error);
@@ -753,8 +747,6 @@ static int open(struct tty_struct *tty, struct file *filp)
tty->driver_data = info;
info->tty = tty;
- if (sanity_check(info, tty->name, "open"))
- return -ENODEV;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s open(), old ref count = %d\n",
@@ -802,6 +794,8 @@ static int open(struct tty_struct *tty, struct file *filp)
cleanup:
if (retval) {
+ if (tty->count == 1)
+ info->tty = 0; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
@@ -816,14 +810,17 @@ static void close(struct tty_struct *tty, struct file *filp)
{
SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
- if (!info || sanity_check(info, tty->name, "close"))
+ if (sanity_check(info, tty->name, "close"))
return;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s close() entry, count=%d\n",
__FILE__,__LINE__, info->device_name, info->count);
- if (!info->count || tty_hung_up_p(filp))
+ if (!info->count)
+ return;
+
+ if (tty_hung_up_p(filp))
goto cleanup;
if ((tty->count == 1) && (info->count != 1)) {
@@ -3775,8 +3772,6 @@ static struct tty_operations ops = {
static int __init synclinkmp_init(void)
{
- SLMP_INFO *info;
-
if (break_on_load) {
synclinkmp_get_text_ptr();
BREAKPOINT();
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index a5241c65d63b..116298c5f7b8 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -1,7 +1,7 @@
/*
* EISA bus support functions for sysfs.
*
- * (C) 2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
+ * (C) 2002, 2003 Marc Zyngier <maz@wild-wind.fr.eu.org>
*
* This code is released under the GPL version 2.
*/
@@ -10,6 +10,7 @@
#include <linux/device.h>
#include <linux/eisa.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@@ -24,7 +25,7 @@ struct eisa_device_info {
char name[DEVICE_NAME_SIZE];
};
-struct eisa_device_info __initdata eisa_table[] = {
+static struct eisa_device_info __initdata eisa_table[] = {
#ifdef CONFIG_EISA_NAMES
#include "devlist.h"
#endif
@@ -32,6 +33,30 @@ struct eisa_device_info __initdata eisa_table[] = {
#define EISA_INFOS (sizeof (eisa_table) / (sizeof (struct eisa_device_info)))
+#define EISA_MAX_FORCED_DEV 16
+#define EISA_FORCED_OFFSET 2
+
+static int enable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET] = { 1, EISA_MAX_FORCED_DEV, };
+static int disable_dev[EISA_MAX_FORCED_DEV + EISA_FORCED_OFFSET] = { 1, EISA_MAX_FORCED_DEV, };
+
+static int is_forced_dev (int *forced_tab,
+ struct eisa_root_device *root,
+ struct eisa_device *edev)
+{
+ int i, x;
+
+ for (i = 0; i < EISA_MAX_FORCED_DEV; i++) {
+ if (!forced_tab[EISA_FORCED_OFFSET + i])
+ return 0;
+
+ x = (root->bus_nr << 8) | edev->slot;
+ if (forced_tab[EISA_FORCED_OFFSET + i] == x)
+ return 1;
+ }
+
+ return 0;
+}
+
static void __init eisa_name_device (struct eisa_device *edev)
{
int i;
@@ -92,7 +117,8 @@ static int eisa_bus_match (struct device *dev, struct device_driver *drv)
return 0;
while (strlen (eids->sig)) {
- if (!strcmp (eids->sig, edev->id.sig)) {
+ if (!strcmp (eids->sig, edev->id.sig) &&
+ edev->state & EISA_CONFIG_ENABLED) {
edev->id.driver_data = eids->driver_data;
return 1;
}
@@ -132,41 +158,160 @@ static ssize_t eisa_show_sig (struct device *dev, char *buf)
static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
-static int __init eisa_register_device (struct eisa_root_device *root,
- struct eisa_device *edev,
- char *sig, int slot)
+static ssize_t eisa_show_state (struct device *dev, char *buf)
+{
+ struct eisa_device *edev = to_eisa_device (dev);
+ return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
+
+static int __init eisa_init_device (struct eisa_root_device *root,
+ struct eisa_device *edev,
+ int slot)
{
+ char *sig;
+ unsigned long sig_addr;
+ int i;
+
+ sig_addr = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+
+ if (!(sig = decode_eisa_sig (sig_addr)))
+ return -1; /* No EISA device here */
+
memcpy (edev->id.sig, sig, EISA_SIG_LEN);
edev->slot = slot;
+ edev->state = inb (SLOT_ADDRESS (root, slot) + EISA_CONFIG_OFFSET) & EISA_CONFIG_ENABLED;
edev->base_addr = SLOT_ADDRESS (root, slot);
- edev->dma_mask = 0xffffffff; /* Default DMA mask */
+ edev->dma_mask = root->dma_mask; /* Default DMA mask */
eisa_name_device (edev);
edev->dev.parent = root->dev;
edev->dev.bus = &eisa_bus_type;
edev->dev.dma_mask = &edev->dma_mask;
sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot);
- edev->res.name = edev->dev.name;
+ for (i = 0; i < EISA_MAX_RESOURCES; i++)
+ edev->res[i].name = edev->dev.name;
+
+ if (is_forced_dev (enable_dev, root, edev))
+ edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED;
+
+ if (is_forced_dev (disable_dev, root, edev))
+ edev->state = EISA_CONFIG_FORCED;
+
+ return 0;
+}
+static int __init eisa_register_device (struct eisa_device *edev)
+{
if (device_register (&edev->dev))
return -1;
device_create_file (&edev->dev, &dev_attr_signature);
+ device_create_file (&edev->dev, &dev_attr_enabled);
+
+ return 0;
+}
+
+static int __init eisa_request_resources (struct eisa_root_device *root,
+ struct eisa_device *edev,
+ int slot)
+{
+ int i;
+
+ for (i = 0; i < EISA_MAX_RESOURCES; i++) {
+ /* Don't register resource for slot 0, since this is
+ * very likely to fail... :-( Instead, grab the EISA
+ * id, now we can display something in /proc/ioports.
+ */
+
+ /* Only one region for mainboard */
+ if (!slot && i > 0) {
+ edev->res[i].start = edev->res[i].end = 0;
+ continue;
+ }
+
+ if (slot) {
+ edev->res[i].name = NULL;
+ edev->res[i].start = SLOT_ADDRESS (root, slot) + (i * 0x400);
+ edev->res[i].end = edev->res[i].start + 0xff;
+ edev->res[i].flags = IORESOURCE_IO;
+ } else {
+ edev->res[i].name = NULL;
+ edev->res[i].start = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+ edev->res[i].end = edev->res[i].start + 3;
+ edev->res[i].flags = IORESOURCE_BUSY;
+ }
+
+ if (request_resource (root->res, &edev->res[i]))
+ goto failed;
+ }
return 0;
+
+ failed:
+ while (--i >= 0)
+ release_resource (&edev->res[i]);
+
+ return -1;
+}
+
+static void __init eisa_release_resources (struct eisa_device *edev)
+{
+ int i;
+
+ for (i = 0; i < EISA_MAX_RESOURCES; i++)
+ if (edev->res[i].start || edev->res[i].end)
+ release_resource (&edev->res[i]);
}
static int __init eisa_probe (struct eisa_root_device *root)
{
int i, c;
- char *str;
- unsigned long sig_addr;
struct eisa_device *edev;
printk (KERN_INFO "EISA: Probing bus %d at %s\n",
root->bus_nr, root->dev->name);
+
+ /* First try to get hold of slot 0. If there is no device
+ * here, simply fail, unless root->force_probe is set. */
- for (c = 0, i = 0; i <= root->slots; i++) {
+ if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
+ printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+ return -ENOMEM;
+ }
+
+ memset (edev, 0, sizeof (*edev));
+
+ if (eisa_request_resources (root, edev, 0)) {
+ printk (KERN_WARNING \
+ "EISA: Cannot allocate resource for mainboard\n");
+ kfree (edev);
+ if (!root->force_probe)
+ return -EBUSY;
+ goto force_probe;
+ }
+
+ if (eisa_init_device (root, edev, 0)) {
+ eisa_release_resources (edev);
+ kfree (edev);
+ if (!root->force_probe)
+ return -ENODEV;
+ goto force_probe;
+ }
+
+ printk (KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+
+ if (eisa_register_device (edev)) {
+ printk (KERN_ERR "EISA: Failed to register %s\n",
+ edev->id.sig);
+ eisa_release_resources (edev);
+ kfree (edev);
+ }
+
+ force_probe:
+
+ for (c = 0, i = 1; i <= root->slots; i++) {
if (!(edev = kmalloc (sizeof (*edev), GFP_KERNEL))) {
printk (KERN_ERR "EISA: Out of memory for slot %d\n",
i);
@@ -175,24 +320,7 @@ static int __init eisa_probe (struct eisa_root_device *root)
memset (edev, 0, sizeof (*edev));
- /* Don't register resource for slot 0, since this is
- * very likely to fail... :-( Instead, grab the EISA
- * id, now we can display something in /proc/ioports.
- */
-
- if (i) {
- edev->res.name = NULL;
- edev->res.start = SLOT_ADDRESS (root, i);
- edev->res.end = edev->res.start + 0xfff;
- edev->res.flags = IORESOURCE_IO;
- } else {
- edev->res.name = NULL;
- edev->res.start = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
- edev->res.end = edev->res.start + 3;
- edev->res.flags = IORESOURCE_BUSY;
- }
-
- if (request_resource (root->res, &edev->res)) {
+ if (eisa_request_resources (root, edev, i)) {
printk (KERN_WARNING \
"Cannot allocate resource for EISA slot %d\n",
i);
@@ -200,30 +328,41 @@ static int __init eisa_probe (struct eisa_root_device *root)
continue;
}
- sig_addr = SLOT_ADDRESS (root, i) + EISA_VENDOR_ID_OFFSET;
-
- if (!(str = decode_eisa_sig (sig_addr))) {
- release_resource (&edev->res);
+ if (eisa_init_device (root, edev, i)) {
+ eisa_release_resources (edev);
kfree (edev);
continue;
}
- if (!i)
- printk (KERN_INFO "EISA: Motherboard %s detected\n",
- str);
- else {
- printk (KERN_INFO "EISA: slot %d : %s detected.\n",
- i, str);
-
- c++;
+ printk (KERN_INFO "EISA: slot %d : %s detected",
+ i, edev->id.sig);
+
+ switch (edev->state) {
+ case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
+ printk (" (forced enabled)");
+ break;
+
+ case EISA_CONFIG_FORCED:
+ printk (" (forced disabled)");
+ break;
+
+ case 0:
+ printk (" (disabled)");
+ break;
}
+
+ printk (".\n");
- if (eisa_register_device (root, edev, str, i)) {
- printk (KERN_ERR "EISA: Failed to register %s\n", str);
- release_resource (&edev->res);
+ c++;
+
+ if (eisa_register_device (edev)) {
+ printk (KERN_ERR "EISA: Failed to register %s\n",
+ edev->id.sig);
+ eisa_release_resources (edev);
kfree (edev);
}
}
+
printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
return 0;
@@ -274,6 +413,13 @@ static int __init eisa_init (void)
return 0;
}
+/* Couldn't use intarray with checking on... :-( */
+#undef param_check_intarray
+#define param_check_intarray(name, p)
+
+module_param(enable_dev, intarray, 0444);
+module_param(disable_dev, intarray, 0444);
+
postcore_initcall (eisa_init);
EXPORT_SYMBOL (eisa_bus_type);
diff --git a/drivers/eisa/eisa.ids b/drivers/eisa/eisa.ids
index 819f9470d7c9..ed69837d8b74 100644
--- a/drivers/eisa/eisa.ids
+++ b/drivers/eisa/eisa.ids
@@ -504,6 +504,7 @@ DTK0001 "DTK PLM-3300I 80486 EISA Board"
DTK0003 "DTK PLM-3331P EISACACHE486 33/25/50 MHZ"
ECS0580 "DI-580A EISA SCSI Host Adapter"
ECS0590 "DI-590 EISA SCSI Cache Host Adapter"
+EGL0101 "Eagle Technology EP3210 EtherXpert EISA Adapter"
ELS8041 "ELSA WINNER 1000 Enhanced VGA"
ETI1001 "NE3300 Ethernet Rev. C & D"
EVX0002 "PN-3000 System Board"
@@ -515,6 +516,9 @@ FIX1516 "15-16MB Memory Hole Patch - Netserver LF/LC 5/66"
FSI2001 "ESA-200 ATM"
FSI2002 "ESA-200A ATM"
FSI2003 "ESA-200E ATM"
+GCI0101 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adpater"
+GCI0102 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adapter"
+GCI0103 "Gateway G/Ethernet 32EB -- 32-Bit EISA Bus Master Ethernet Adapter"
GDT2001 "GDT2000/GDT2020 Fast-SCSI Cache Controller - Rev. 1.0"
GDT3001 "GDT3000/GDT3020 Dual Channel SCSI Controller - Rev. 1.0"
GDT3002 "GDT30x0A Cache Controller"
@@ -1138,12 +1142,14 @@ NON0501 "c't Universal 16-Bit Sound Adapter"
NON0601 "c't Universal 8-Bit Adapter"
NSS0011 "Newport Systems Solutions WNIC Adapter"
NVL0701 "Novell NE3200 Bus Master Ethernet"
+NVL0702 "Novell NE3200T Bus Master Ethernet"
NVL0901 "Novell NE2100 Ethernet/Cheapernet Adapter"
NVL1001 "Novell NMSL (Netware Mirrored Server Link)"
NVL1201 "Novell NE32HUB 32-bit Base EISA Adapter"
NVL1301 "Novell NE32HUB 32-bit TPE EISA Adapter"
NVL1401 "Novell NE32HUB PME ISA Adapter"
NVL1501 "Novell NE2000PLUS Ethernet Adapter"
+NVL1801 "Eagle Technology NE3210 EISA Ethernet LAN Adapter"
OLC0701 "Olicom ISA 16/4 Token-Ring Network Adapter"
OLC0702 "Olicom OC-3117, ISA 16/4 Adapter (NIC)"
OLC0801 "OC-3118 Olicom ISA 16/4 Token-Ring Network Adapter"
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 635c2997a041..3dedb1997b8d 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -20,7 +20,7 @@
static struct eisa_root_device pci_eisa_root;
static int __devinit pci_eisa_init (struct pci_dev *pdev,
- const struct pci_device_id *ent)
+ const struct pci_device_id *ent)
{
int rc;
@@ -35,6 +35,7 @@ static int __devinit pci_eisa_init (struct pci_dev *pdev,
pci_eisa_root.res = pdev->bus->resource[0];
pci_eisa_root.bus_base_addr = pdev->bus->resource[0]->start;
pci_eisa_root.slots = EISA_MAX_SLOTS;
+ pci_eisa_root.dma_mask = pdev->dma_mask;
if (eisa_root_register (&pci_eisa_root)) {
printk (KERN_ERR "pci_eisa : Could not register EISA root\n");
diff --git a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c
index 12f684f9dc8c..3c384ccfe489 100644
--- a/drivers/eisa/virtual_root.c
+++ b/drivers/eisa/virtual_root.c
@@ -7,12 +7,22 @@
* This code is released under the GPL version 2.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/eisa.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/init.h>
+#if defined(CONFIG_ALPHA_JENSEN) || defined(CONFIG_EISA_VLB_PRIMING)
+#define EISA_FORCE_PROBE_DEFAULT 1
+#else
+#define EISA_FORCE_PROBE_DEFAULT 0
+#endif
+
+static int force_probe = EISA_FORCE_PROBE_DEFAULT;
+
/* The default EISA device parent (virtual root device).
* Now use a platform device, since that's the obvious choice. */
@@ -29,6 +39,7 @@ static struct eisa_root_device eisa_bus_root = {
.bus_base_addr = 0,
.res = &ioport_resource,
.slots = EISA_MAX_SLOTS,
+ .dma_mask = 0xffffffff,
};
static int virtual_eisa_root_init (void)
@@ -39,6 +50,8 @@ static int virtual_eisa_root_init (void)
return r;
}
+ eisa_bus_root.force_probe = force_probe;
+
eisa_root_dev.dev.driver_data = &eisa_bus_root;
if (eisa_root_register (&eisa_bus_root)) {
@@ -51,4 +64,6 @@ static int virtual_eisa_root_init (void)
return 0;
}
+module_param (force_probe, int, 0444);
+
device_initcall (virtual_eisa_root_init);
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index f86304224663..8cdcb9a0a736 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -1514,6 +1514,8 @@ pmac_ide_setup_dma(struct device_node *np, int ix)
ide_hwifs[ix].ide_dma_timeout = &__ide_dma_timeout;
ide_hwifs[ix].ide_dma_retune = &__ide_dma_retune;
ide_hwifs[ix].ide_dma_lostirq = &pmac_ide_dma_lostirq;
+ ide_hwifs[ix].ide_dma_queued_on = &__ide_dma_queued_on;
+ ide_hwifs[ix].ide_dma_queued_off = &__ide_dma_queued_off;
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
if (!noautodma)
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 3fd94842cfb9..e93e9e3fece9 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -56,6 +56,8 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/version.h>
+#include <linux/pci.h>
+
#include <asm/current.h>
#include <asm/uaccess.h>
#include <asm/io.h>
diff --git a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
index 1c087bfc9343..9f4b7cdd2f68 100644
--- a/drivers/macintosh/macserial.c
+++ b/drivers/macintosh/macserial.c
@@ -76,6 +76,8 @@ static struct pmu_sleep_notifier serial_sleep_notifier = {
in the order we want. */
#define RECOVERY_DELAY eieio()
+static struct tty_driver *serial_driver;
+
struct mac_zschannel zs_channels[NUM_CHANNELS];
struct mac_serial zs_soft[NUM_CHANNELS];
@@ -2093,12 +2095,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (info->flags & ZILOG_CLOSING) {
interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- return ((info->flags & ZILOG_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
return -EAGAIN;
-#endif
}
/*
@@ -2139,14 +2136,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) ||
!(info->flags & ZILOG_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
- if (info->flags & ZILOG_HUP_NOTIFY)
- retval = -EAGAIN;
- else
- retval = -ERESTARTSYS;
-#else
retval = -EAGAIN;
-#endif
break;
}
if (!(info->flags & ZILOG_CLOSING) &&
@@ -2222,12 +2212,7 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
(info->flags & ZILOG_CLOSING)) {
if (info->flags & ZILOG_CLOSING)
interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
- return ((info->flags & ZILOG_HUP_NOTIFY) ?
- -EAGAIN : -ERESTARTSYS);
-#else
return -EAGAIN;
-#endif
}
/*
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index eaeeb15358f7..744c3273e6e3 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -238,6 +238,7 @@ void __hash_remove(struct hash_cell *hc)
list_del(&hc->name_list);
unregister_with_devfs(hc);
dm_put(hc->md);
+ free_cell(hc);
}
void dm_hash_remove_all(void)
@@ -729,8 +730,7 @@ static int wait_device_event(struct dm_ioctl *param, struct dm_ioctl *user)
dm_table_put(table);
dm_put(md);
- yield();
- set_current_state(TASK_RUNNING);
+ schedule();
out:
return results_to_user(user, param, NULL, 0);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 05e6ffc49d3e..2a9ae0ab6823 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -783,10 +783,9 @@ int dm_suspend(struct mapped_device *md)
if (!atomic_read(&md->pending))
break;
- yield();
+ io_schedule();
}
-
- current->state = TASK_RUNNING;
+ set_current_state(TASK_RUNNING);
down_write(&md->lock);
remove_wait_queue(&md->wait, &wait);
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 9cccfba214c5..abb054dc30e0 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -49,6 +49,7 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/prefetch.h>
+#include <linux/pci.h>
#include <asm/dma.h>
#include <asm/system.h>
#include <asm/io.h>
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index 3b0c9c469ea3..d15606605f81 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -211,9 +211,10 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
case HDIO_GETGEO:
if (tr->getgeo) {
struct hd_geometry g;
+ int ret;
memset(&g, 0, sizeof(g));
- int ret = tr->getgeo(dev, &g);
+ ret = tr->getgeo(dev, &g);
if (ret)
return ret;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 35e9724bb622..19b7d611e38e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1397,7 +1397,7 @@ config CS89x0
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
- depends on NET_PCI && PCI
+ depends on NET_PCI && PCI && TOSHIBA_JMR3927
config DGRS
tristate "Digi Intl. RightSwitch SE-X support"
diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c
index 9d8d7a1e85aa..d102b207be15 100644
--- a/drivers/net/e100/e100_main.c
+++ b/drivers/net/e100/e100_main.c
@@ -1085,10 +1085,10 @@ e100_xmit_frame(struct sk_buff *skb, struct net_device *dev)
goto exit1;
}
- e100_prepare_xmit_buff(bdp, skb);
-
bdp->drv_stats.net_stats.tx_bytes += skb->len;
+ e100_prepare_xmit_buff(bdp, skb);
+
dev->trans_start = jiffies;
exit1:
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index a2d387ced051..99d7afc609bc 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -212,13 +212,6 @@ static int irtty_set_dtr_rts(struct sir_dev *dev, int dtr, int rts)
/* called from sir_dev when there is more data to send
* context is either netdev->hard_xmit or some transmit-completion bh
* i.e. we are under spinlock here and must not sleep.
- *
- * Note: as of 2.5.44 the usb-serial driver calls down() on a semaphore
- * hence we are hitting the might_sleep bugcatcher. IMHO the whole tty-api
- * would be pretty pointless if write_room/write would be allowed to sleep.
- * Furthermore other tty ldiscs (like ppp) do also require the driver not
- * to sleep there. Hence this is considered a current limitation of
- * usb-serial.
*/
static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t len)
@@ -269,16 +262,15 @@ static void irtty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
struct sirtty_cb *priv = tty->disc_data;
int i;
- if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
- return;
- /* Please use ASSERT - Fix ASSERT as needed - Jean II */
+ ASSERT(priv != NULL, return;);
+ ASSERT(priv->magic == IRTTY_MAGIC, return;);
if (unlikely(count==0)) /* yes, this happens */
return;
dev = priv->dev;
if (!dev) {
- printk(KERN_ERR "%s(), not ready yet!\n", __FUNCTION__);
+ WARNING("%s(), not ready yet!\n", __FUNCTION__);
return;
}
@@ -306,8 +298,8 @@ static int irtty_receive_room(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
- return 0;
+ ASSERT(priv != NULL, return 0;);
+ ASSERT(priv->magic == IRTTY_MAGIC, return 0;);
return 65536; /* We can handle an infinite amount of data. :-) */
}
@@ -323,8 +315,8 @@ static void irtty_write_wakeup(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- if (unlikely(!priv || priv->magic!=IRTTY_MAGIC))
- return;
+ ASSERT(priv != NULL, return;);
+ ASSERT(priv->magic == IRTTY_MAGIC, return;);
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
@@ -559,7 +551,7 @@ static int irtty_open(struct tty_struct *tty)
up(&irtty_sem);
- printk(KERN_INFO "%s - done\n", __FUNCTION__);
+ IRDA_DEBUG(0, "%s - %s: irda line discipline opened\n", __FUNCTION__, tty->name);
return 0;
@@ -580,8 +572,8 @@ static void irtty_close(struct tty_struct *tty)
{
struct sirtty_cb *priv = tty->disc_data;
- if (!priv || priv->magic != IRTTY_MAGIC)
- return;
+ ASSERT(priv != NULL, return;);
+ ASSERT(priv->magic == IRTTY_MAGIC, return;);
/* Hm, with a dongle attached the dongle driver wants
* to close the dongle - which requires the use of
@@ -610,6 +602,8 @@ static void irtty_close(struct tty_struct *tty)
tty->driver->stop(tty);
kfree(priv);
+
+ IRDA_DEBUG(0, "%s - %s: irda line discipline closed\n", __FUNCTION__, tty->name);
}
/* ------------------------------------------------------- */
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index d0af0c633be7..6572d11bbc1f 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -201,14 +201,12 @@ void sirdev_write_complete(struct sir_dev *dev)
int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
{
if (!dev || !dev->netdev) {
- IRDA_DEBUG(0, "%s(), not ready yet!\n", __FUNCTION__);
- /* Use WARNING instead of IRDA_DEBUG */
+ WARNING("%s(), not ready yet!\n", __FUNCTION__);
return -1;
}
if (!dev->irlap) {
- IRDA_DEBUG(0, "%s - too early: %p / %d!\n", __FUNCTION__, cp, count);
- /* Use WARNING instead of IRDA_DEBUG */
+ WARNING("%s - too early: %p / %d!\n", __FUNCTION__, cp, count);
return -1;
}
@@ -218,7 +216,7 @@ int sirdev_receive(struct sir_dev *dev, const unsigned char *cp, size_t count)
*/
irda_device_set_media_busy(dev->netdev, TRUE);
dev->stats.rx_dropped++;
- printk(KERN_INFO "%s; rx-drop: %d\n", __FUNCTION__, count);
+ IRDA_DEBUG(0, "%s; rx-drop: %d\n", __FUNCTION__, count);
return 0;
}
@@ -431,7 +429,6 @@ static int sirdev_alloc_buffers(struct sir_dev *dev)
return -ENOMEM;
skb_reserve(dev->rx_buff.skb, 1);
dev->rx_buff.head = dev->rx_buff.skb->data;
- /* No need to memset the buffer, unless you are really pedantic */
dev->tx_buff.head = kmalloc(dev->tx_buff.truesize, GFP_KERNEL);
if (dev->tx_buff.head == NULL) {
@@ -439,8 +436,6 @@ static int sirdev_alloc_buffers(struct sir_dev *dev)
dev->rx_buff.skb = NULL;
dev->rx_buff.head = NULL;
return -ENOMEM;
- /* Hu ??? This should not be here, Martin ? */
- memset(dev->tx_buff.head, 0, dev->tx_buff.truesize);
}
dev->tx_buff.data = dev->tx_buff.head;
@@ -492,7 +487,7 @@ static int sirdev_open(struct net_device *ndev)
netif_wake_queue(ndev);
- printk(KERN_INFO "%s - done, speed = %d\n", __FUNCTION__, dev->speed);
+ IRDA_DEBUG(2, "%s - done, speed = %d\n", __FUNCTION__, dev->speed);
return 0;
@@ -512,7 +507,7 @@ static int sirdev_close(struct net_device *ndev)
struct sir_dev *dev = ndev->priv;
const struct sir_driver *drv;
- printk(KERN_INFO "%s\n", __FUNCTION__);
+// IRDA_DEBUG(0, "%s\n", __FUNCTION__);
netif_stop_queue(ndev);
@@ -570,7 +565,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
struct net_device *ndev;
struct sir_dev *dev;
- printk(KERN_INFO "%s - %s\n", __FUNCTION__, name);
+ IRDA_DEBUG(0, "%s - %s\n", __FUNCTION__, name);
/* instead of adding tests to protect against drv->do_write==NULL
* at several places we refuse to create a sir_dev instance for
@@ -584,8 +579,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
*/
dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
- printk(KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
+ ERROR("%s - Can't allocate memory for IrDA control block!\n", __FUNCTION__);
goto out;
}
memset(dev, 0, sizeof(*dev));
@@ -638,7 +632,7 @@ int sirdev_put_instance(struct sir_dev *dev)
{
int err = 0;
- printk(KERN_INFO "%s\n", __FUNCTION__);
+ IRDA_DEBUG(0, "%s\n", __FUNCTION__);
atomic_set(&dev->enable_rx, 0);
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index cc38b8809b14..5e7f455432c2 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -19,6 +19,7 @@
#include <linux/smp_lock.h>
#include <linux/completion.h>
#include <linux/delay.h>
+#include <linux/suspend.h>
#include <net/irda/irda.h>
@@ -107,44 +108,12 @@ static void run_irda_queue(void)
spin_unlock_irqrestore(&irda_rq_queue.lock, flags);
}
-static int irda_rt_prio = 0; /* MODULE_PARM? */
-
static int irda_thread(void *startup)
{
DECLARE_WAITQUEUE(wait, current);
daemonize("kIrDAd");
- set_fs(KERNEL_DS);
-
- if (irda_rt_prio > 0) {
-#if 0 /* works but requires EXPORT_SYMBOL(setscheduler) */
- struct sched_param param;
-
- param.sched_priority = irda_rt_prio;
- setscheduler(0, SCHED_FIFO, &param);
-#endif
-
-#if 0 /* doesn't work - has some tendency to trigger instant reboot!
- * looks like we would have to deactivate current on the
- * runqueue - which is only possible inside of kernel/sched.h
- */
-
- /* runqueues are per-cpu and we are current on this cpu. Hence
- * The tasklist_lock with irq-off protects our runqueue too
- * and we don't have to lock it (which would be impossible,
- * because it is private in kernel/sched.c)
- */
-
- read_lock_irq(&tasklist_lock);
- current->rt_priority = (irda_rt_prio<MAX_RT_PRIO)
- ? irda_rt_prio : MAX_RT_PRIO-1;
- current->policy = SCHED_FIFO;
- current->prio = MAX_USER_RT_PRIO-1 - irda_rt_prio;
- read_unlock_irq(&tasklist_lock);
-#endif
- }
-
irda_rq_queue.thread = current;
complete((struct completion *)startup);
@@ -166,6 +135,10 @@ static int irda_thread(void *startup)
set_task_state(current, TASK_RUNNING);
remove_wait_queue(&irda_rq_queue.kick, &wait);
+ /* make swsusp happy with our thread */
+ if (current->flags & PF_FREEZE)
+ refrigerator(PF_IOTHREAD);
+
run_irda_queue();
}
@@ -442,7 +415,6 @@ static void irda_config_fsm(void *data)
case SIRDEV_STATE_COMPLETE:
/* config change finished, so we are not busy any longer */
sirdev_enable_rx(dev);
- printk(KERN_INFO "%s - up\n", __FUNCTION__);
up(&fsm->sem);
return;
}
@@ -462,9 +434,7 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
struct sir_fsm *fsm = &dev->fsm;
int xmit_was_down;
-// IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
-
- printk(KERN_INFO "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
+ IRDA_DEBUG(2, "%s - state=0x%04x / param=%u\n", __FUNCTION__, initial_state, param);
if (in_interrupt()) {
if (down_trylock(&fsm->sem)) {
@@ -474,12 +444,10 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
}
else
down(&fsm->sem);
- printk(KERN_INFO "%s - down\n", __FUNCTION__);
if (fsm->state == SIRDEV_STATE_DEAD) {
/* race with sirdev_close should never happen */
ERROR("%s(), instance staled!\n", __FUNCTION__);
- printk(KERN_INFO "%s - up\n", __FUNCTION__);
up(&fsm->sem);
return -ESTALE; /* or better EPIPE? */
}
@@ -501,7 +469,6 @@ int sirdev_schedule_request(struct sir_dev *dev, int initial_state, unsigned par
atomic_set(&dev->enable_rx, 1);
if (!xmit_was_down)
netif_wake_queue(dev->netdev);
- printk(KERN_INFO "%s - up\n", __FUNCTION__);
up(&fsm->sem);
return -EAGAIN;
}
diff --git a/drivers/net/wan/comx.c b/drivers/net/wan/comx.c
index 1039bf85ea0a..8cd73bc9a3d5 100644
--- a/drivers/net/wan/comx.c
+++ b/drivers/net/wan/comx.c
@@ -86,7 +86,7 @@ static struct comx_protocol *comx_lines = NULL;
static int comx_mkdir(struct inode *, struct dentry *, int);
static int comx_rmdir(struct inode *, struct dentry *);
-static struct dentry *comx_lookup(struct inode *, struct dentry *);
+static struct dentry *comx_lookup(struct inode *, struct dentry *, struct nameidata *);
static struct inode_operations comx_root_inode_ops = {
.lookup = comx_lookup,
@@ -922,7 +922,7 @@ static int comx_rmdir(struct inode *dir, struct dentry *dentry)
return 0;
}
-static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *comx_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct proc_dir_entry *de;
struct inode *inode = NULL;
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index f003d03844d3..fd0b3dfeeb19 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -177,11 +177,8 @@ EXPORT_SYMBOL(unregister_hdlc_device);
struct packet_type hdlc_packet_type=
{
- __constant_htons(ETH_P_HDLC),
- NULL,
- hdlc_rcv,
- NULL,
- NULL
+ .type = __constant_htons(ETH_P_HDLC),
+ .func = hdlc_rcv,
};
diff --git a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
index 547ef6adffe9..92959266a026 100644
--- a/drivers/parisc/eisa.c
+++ b/drivers/parisc/eisa.c
@@ -378,19 +378,21 @@ static int __devinit eisa_probe(struct parisc_device *dev)
}
}
eisa_eeprom_init(eisa_dev.eeprom_addr);
- eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
+ result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
init_eisa_pic();
- /* FIXME : Get the number of slots from the enumerator, not a
- * hadcoded value. Also don't enumerate the bus twice. */
- eisa_dev.root.dev = &dev->dev;
- dev->dev.driver_data = &eisa_dev.root;
- eisa_dev.root.bus_base_addr = 0;
- eisa_dev.root.res = &eisa_dev.hba.io_space;
- eisa_dev.root.slots = EISA_MAX_SLOTS;
- if (eisa_root_register (&eisa_dev.root)) {
- printk(KERN_ERR "EISA: Failed to register EISA root\n");
- return -1;
+ if (result >= 0) {
+ /* FIXME : Don't enumerate the bus twice. */
+ eisa_dev.root.dev = &dev->dev;
+ dev->dev.driver_data = &eisa_dev.root;
+ eisa_dev.root.bus_base_addr = 0;
+ eisa_dev.root.res = &eisa_dev.hba.io_space;
+ eisa_dev.root.slots = result;
+ eisa_dev.root.dma_mask = 0xffffffff; /* wild guess */
+ if (eisa_root_register (&eisa_dev.root)) {
+ printk(KERN_ERR "EISA: Failed to register EISA root\n");
+ return -1;
+ }
}
return 0;
diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c
index ebd15f128ffb..6d8aae003f6c 100644
--- a/drivers/parisc/eisa_enumerator.c
+++ b/drivers/parisc/eisa_enumerator.c
@@ -438,6 +438,10 @@ static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
id = le32_to_cpu(inl(SLOT2PORT(slot)+EPI));
if (0xffffffff == id) {
+ /* Maybe we didn't expect a card to be here... */
+ if (es->eisa_slot_id == 0xffffffff)
+ return -1;
+
/* this board is not here or it does not
* support readid
*/
@@ -499,8 +503,7 @@ int eisa_enumerator(unsigned long eeprom_addr,
(&eeprom_buf[HPEE_SLOT_INFO(i)]);
if (-1==init_slot(i+1, es)) {
- return -1;
-
+ continue;
}
if (es->config_data_offset < HPEE_MAX_LENGTH) {
@@ -513,6 +516,6 @@ int eisa_enumerator(unsigned long eeprom_addr,
return -1;
}
}
- return 0;
+ return eh->num_slots;
}
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 3af6ad4adbe7..4e8ddf184341 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -385,7 +385,7 @@ static void add_host_bridge (acpi_handle *handle, int seg, int bus)
bridge->seg = seg;
bridge->bus = bus;
- bridge->pci_bus = pci_find_bus(bus);
+ bridge->pci_bus = pci_find_bus(seg, bus);
bridge->res_lock = SPIN_LOCK_UNLOCKED;
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 8ffe245a1ca2..88bc69c50539 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -395,7 +395,7 @@ static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
/* Scan behind bridge */
n = pci_scan_bridge(bus, dev, max, 2);
- child = pci_find_bus(max + 1);
+ child = pci_find_bus(0, max + 1);
if (!child)
return -ENODEV;
pci_proc_attach_bus(child);
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 1e44444e6287..1f0fa666cf8b 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -774,7 +774,7 @@ static u8 bus_structure_fixup (u8 busno)
struct pci_dev *dev;
u16 l;
- if (pci_find_bus(busno) || !(ibmphp_find_same_bus_num (busno)))
+ if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num (busno)))
return 1;
bus = kmalloc (sizeof (*bus), GFP_KERNEL);
@@ -819,7 +819,7 @@ static int ibm_configure_device (struct pci_func *func)
func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
- struct pci_bus *bus = pci_find_bus(func->busno);
+ struct pci_bus *bus = pci_find_bus(0, func->busno);
if (!bus)
return 0;
@@ -1335,7 +1335,7 @@ static int __init ibmphp_init (void)
goto exit;
}
- bus = pci_find_bus(0);
+ bus = pci_find_bus(0, 0);
if (!bus) {
err ("Can't find the root pci bus, can not continue\n");
rc = -ENODEV;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 4e13d7141b78..dc560bf77421 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -3,6 +3,8 @@
*
* (C) Copyright 2002 Greg Kroah-Hartman
* (C) Copyright 2002 IBM Corp.
+ * (C) Copyright 2003 Matthew Wilcox
+ * (C) Copyright 2003 Hewlett-Packard
*
* File attributes for PCI devices
*
@@ -60,6 +62,108 @@ pci_show_resources(struct device * dev, char * buf)
static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
+static ssize_t
+pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+ unsigned int size = 64;
+
+ /* Several chips lock up trying to read undefined config space */
+ if (capable(CAP_SYS_ADMIN)) {
+ size = 256;
+ } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
+ size = 128;
+ }
+
+ if (off > size)
+ return 0;
+ if (off + count > size) {
+ size -= off;
+ count = size;
+ } else {
+ size = count;
+ }
+
+ while (off & 3) {
+ unsigned char val;
+ pci_read_config_byte(dev, off, &val);
+ buf[off] = val;
+ off++;
+ if (--size == 0)
+ break;
+ }
+
+ while (size > 3) {
+ unsigned int val;
+ pci_read_config_dword(dev, off, &val);
+ buf[off] = val & 0xff;
+ buf[off + 1] = (val >> 8) & 0xff;
+ buf[off + 2] = (val >> 16) & 0xff;
+ buf[off + 3] = (val >> 24) & 0xff;
+ off += 4;
+ size -= 4;
+ }
+
+ while (size > 0) {
+ unsigned char val;
+ pci_read_config_byte(dev, off, &val);
+ buf[off] = val;
+ off++;
+ --size;
+ }
+
+ return count;
+}
+
+static ssize_t
+pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
+ unsigned int size = count;
+
+ if (off > 256)
+ return 0;
+ if (off + count > 256) {
+ size = 256 - off;
+ count = size;
+ }
+
+ while (off & 3) {
+ pci_write_config_byte(dev, off, buf[off]);
+ off++;
+ if (--size == 0)
+ break;
+ }
+
+ while (size > 3) {
+ unsigned int val = buf[off];
+ val |= (unsigned int) buf[off + 1] << 8;
+ val |= (unsigned int) buf[off + 2] << 16;
+ val |= (unsigned int) buf[off + 3] << 24;
+ pci_write_config_dword(dev, off, val);
+ off += 4;
+ size -= 4;
+ }
+
+ while (size > 0) {
+ pci_write_config_byte(dev, off, buf[off]);
+ off++;
+ --size;
+ }
+
+ return count;
+}
+
+static struct bin_attribute pci_config_attr = {
+ .attr = {
+ .name = "config",
+ .mode = S_IRUGO | S_IWUSR,
+ },
+ .size = 256,
+ .read = pci_read_config,
+ .write = pci_write_config,
+};
+
void pci_create_sysfs_dev_files (struct pci_dev *pdev)
{
struct device *dev = &pdev->dev;
@@ -72,4 +176,5 @@ void pci_create_sysfs_dev_files (struct pci_dev *pdev)
device_create_file (dev, &dev_attr_class);
device_create_file (dev, &dev_attr_irq);
device_create_file (dev, &dev_attr_resource);
+ sysfs_create_bin_file(&dev->kobj, &pci_config_attr);
}
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 3288e401d914..2ad19d3f928e 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -29,7 +29,6 @@ extern int pci_remove_device_safe(struct pci_dev *dev);
extern unsigned char pci_max_busnr(void);
extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
-extern struct pci_bus *pci_find_bus(unsigned char busnr);
struct pci_dev_wrapped {
struct pci_dev *dev;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 0894f4aed331..ccd50ca202f8 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -633,27 +633,10 @@ unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
return max;
}
-int __devinit pci_bus_exists(const struct list_head *list, int nr)
-{
- const struct pci_bus *b;
-
- list_for_each_entry(b, list, node) {
- if (b->number == nr || pci_bus_exists(&b->children, nr))
- return 1;
- }
- return 0;
-}
-
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata)
{
struct pci_bus *b;
- if (pci_bus_exists(&pci_root_buses, bus)) {
- /* If we already got to this bus through a different bridge, ignore it */
- DBG("PCI: Bus %02x already known\n", bus);
- return NULL;
- }
-
b = pci_alloc_bus();
if (!b)
return NULL;
@@ -667,6 +650,14 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
b->sysdata = sysdata;
b->ops = ops;
+ if (pci_find_bus(pci_domain_nr(b), bus)) {
+ /* If we already got to this bus through a different bridge, ignore it */
+ DBG("PCI: Bus %02x already known\n", bus);
+ kfree(b->dev);
+ kfree(b);
+ return NULL;
+ }
+
list_add_tail(&b->node, &pci_root_buses);
memset(b->dev,0,sizeof(*(b->dev)));
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index 85c74126ee6a..366f1f16fb2f 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -7,12 +7,14 @@
* Copyright 2003 -- Greg Kroah-Hartman <greg@kroah.com>
*/
+#include <linux/init.h>
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/interrupt.h>
spinlock_t pci_bus_lock = SPIN_LOCK_UNLOCKED;
-static struct pci_bus *
+static struct pci_bus * __devinit
pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
{
struct pci_bus* child;
@@ -30,22 +32,24 @@ pci_do_find_bus(struct pci_bus* bus, unsigned char busnr)
}
/**
- * pci_find_bus - locate PCI bus from a given bus number
+ * pci_find_bus - locate PCI bus from a given domain and bus number
+ * @domain: number of PCI domain to search
* @busnr: number of desired PCI bus
*
- * Given a PCI bus number, the desired PCI bus is located in system
- * global list of PCI buses. If the bus is found, a pointer to its
+ * Given a PCI bus number and domain number, the desired PCI bus is located
+ * in the global list of PCI buses. If the bus is found, a pointer to its
* data structure is returned. If no bus is found, %NULL is returned.
*/
-struct pci_bus *
-pci_find_bus(unsigned char busnr)
+struct pci_bus * __devinit pci_find_bus(int domain, int busnr)
{
- struct pci_bus* bus = NULL;
- struct pci_bus* tmp_bus;
+ struct pci_bus *bus = NULL;
+ struct pci_bus *tmp_bus;
while ((bus = pci_find_next_bus(bus)) != NULL) {
+ if (pci_domain_nr(bus) != domain)
+ continue;
tmp_bus = pci_do_find_bus(bus, busnr);
- if(tmp_bus)
+ if (tmp_bus)
return tmp_bus;
}
return NULL;
@@ -66,7 +70,7 @@ pci_find_next_bus(const struct pci_bus *from)
struct list_head *n;
struct pci_bus *b = NULL;
- WARN_ON(irqs_disabled());
+ WARN_ON(in_interrupt());
spin_lock(&pci_bus_lock);
n = from ? from->node.next : pci_root_buses.next;
if (n != &pci_root_buses)
@@ -125,7 +129,7 @@ pci_find_subsys(unsigned int vendor, unsigned int device,
struct list_head *n;
struct pci_dev *dev;
- WARN_ON(irqs_disabled());
+ WARN_ON(in_interrupt());
spin_lock(&pci_bus_lock);
n = from ? from->global_list.next : pci_devices.next;
@@ -190,7 +194,7 @@ pci_get_subsys(unsigned int vendor, unsigned int device,
struct list_head *n;
struct pci_dev *dev;
- WARN_ON(irqs_disabled());
+ WARN_ON(in_interrupt());
spin_lock(&pci_bus_lock);
n = from ? from->global_list.next : pci_devices.next;
@@ -256,7 +260,7 @@ pci_find_device_reverse(unsigned int vendor, unsigned int device, const struct p
struct list_head *n;
struct pci_dev *dev;
- WARN_ON(irqs_disabled());
+ WARN_ON(in_interrupt());
spin_lock(&pci_bus_lock);
n = from ? from->global_list.prev : pci_devices.prev;
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index eb2094bf72d0..e2b7388f7ec2 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -259,7 +259,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_PORT; i++) {
if (pnp_port_valid(dev, i)) {
pnp_printf(buffer,"io");
- pnp_printf(buffer," 0x%lx-0x%lx \n",
+ if (pnp_port_flags(dev, i) & IORESOURCE_DISABLED)
+ pnp_printf(buffer," disabled\n");
+ else
+ pnp_printf(buffer," 0x%lx-0x%lx\n",
pnp_port_start(dev, i),
pnp_port_end(dev, i));
}
@@ -267,7 +270,10 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_MEM; i++) {
if (pnp_mem_valid(dev, i)) {
pnp_printf(buffer,"mem");
- pnp_printf(buffer," 0x%lx-0x%lx \n",
+ if (pnp_mem_flags(dev, i) & IORESOURCE_DISABLED)
+ pnp_printf(buffer," disabled\n");
+ else
+ pnp_printf(buffer," 0x%lx-0x%lx\n",
pnp_mem_start(dev, i),
pnp_mem_end(dev, i));
}
@@ -275,13 +281,21 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
for (i = 0; i < PNP_MAX_IRQ; i++) {
if (pnp_irq_valid(dev, i)) {
pnp_printf(buffer,"irq");
- pnp_printf(buffer," %ld \n", pnp_irq(dev, i));
+ if (pnp_irq_flags(dev, i) & IORESOURCE_DISABLED)
+ pnp_printf(buffer," disabled\n");
+ else
+ pnp_printf(buffer," %ld\n",
+ pnp_irq(dev, i));
}
}
for (i = 0; i < PNP_MAX_DMA; i++) {
if (pnp_dma_valid(dev, i)) {
pnp_printf(buffer,"dma");
- pnp_printf(buffer," %ld \n", pnp_dma(dev, i));
+ if (pnp_dma_flags(dev, i) & IORESOURCE_DISABLED)
+ pnp_printf(buffer," disabled\n");
+ else
+ pnp_printf(buffer," %ld\n",
+ pnp_dma(dev, i));
}
}
ret = (buffer->curr - buf);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index a56dfac58b36..d902dfc47164 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -45,9 +45,15 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
flags = &dev->res.port_resource[idx].flags;
/* set the initial values */
+ *flags = *flags | rule->flags | IORESOURCE_IO;
+
+ if (!rule->size) {
+ *flags |= IORESOURCE_DISABLED;
+ return 1; /* skip disabled resource requests */
+ }
+
*start = rule->min;
*end = *start + rule->size - 1;
- *flags = *flags | rule->flags | IORESOURCE_IO;
/* run through until pnp_check_port is happy */
while (!pnp_check_port(dev, idx)) {
@@ -81,8 +87,6 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
flags = &dev->res.mem_resource[idx].flags;
/* set the initial values */
- *start = rule->min;
- *end = *start + rule->size -1;
*flags = *flags | rule->flags | IORESOURCE_MEM;
/* convert pnp flags to standard Linux flags */
@@ -95,6 +99,14 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
*flags |= IORESOURCE_SHADOWABLE;
+ if (!rule->size) {
+ *flags |= IORESOURCE_DISABLED;
+ return 1; /* skip disabled resource requests */
+ }
+
+ *start = rule->min;
+ *end = *start + rule->size -1;
+
/* run through until pnp_check_mem is happy */
while (!pnp_check_mem(dev, idx)) {
*start += rule->align;
@@ -135,6 +147,11 @@ static int pnp_assign_irq(struct pnp_dev * dev, struct pnp_irq *rule, int idx)
/* set the initial values */
*flags = *flags | rule->flags | IORESOURCE_IRQ;
+ if (!rule->map) {
+ *flags |= IORESOURCE_DISABLED;
+ return 1; /* skip disabled resource requests */
+ }
+
for (i = 0; i < 16; i++) {
if(rule->map & (1<<xtab[i])) {
*start = *end = xtab[i];
@@ -175,6 +192,11 @@ static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
/* set the initial values */
*flags = *flags | rule->flags | IORESOURCE_DMA;
+ if (!rule->map) {
+ *flags |= IORESOURCE_DISABLED;
+ return 1; /* skip disabled resource requests */
+ }
+
for (i = 0; i < 8; i++) {
if(rule->map & (1<<xtab[i])) {
*start = *end = xtab[i];
@@ -378,25 +400,24 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res,
dev->res = *res;
if (!(mode & PNP_CONFIG_FORCE)) {
for (i = 0; i < PNP_MAX_PORT; i++) {
- if(pnp_check_port(dev,i))
+ if(!pnp_check_port(dev,i))
goto fail;
}
for (i = 0; i < PNP_MAX_MEM; i++) {
- if(pnp_check_mem(dev,i))
+ if(!pnp_check_mem(dev,i))
goto fail;
}
for (i = 0; i < PNP_MAX_IRQ; i++) {
- if(pnp_check_irq(dev,i))
+ if(!pnp_check_irq(dev,i))
goto fail;
}
for (i = 0; i < PNP_MAX_DMA; i++) {
- if(pnp_check_dma(dev,i))
+ if(!pnp_check_dma(dev,i))
goto fail;
}
}
up(&pnp_res_mutex);
- pnp_auto_config_dev(dev);
kfree(bak);
return 0;
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c
index 978decf7504a..c7c664a3035f 100644
--- a/drivers/pnp/resource.c
+++ b/drivers/pnp/resource.c
@@ -286,6 +286,8 @@ int pnp_check_port(struct pnp_dev * dev, int idx)
continue;
for (tmp = 0; tmp < PNP_MAX_PORT; tmp++) {
if (tdev->res.port_resource[tmp].flags & IORESOURCE_IO) {
+ if (pnp_port_flags(dev, tmp) & IORESOURCE_DISABLED)
+ continue;
tport = &tdev->res.port_resource[tmp].start;
tend = &tdev->res.port_resource[tmp].end;
if (ranged_conflict(port,end,tport,tend))
@@ -340,6 +342,8 @@ int pnp_check_mem(struct pnp_dev * dev, int idx)
continue;
for (tmp = 0; tmp < PNP_MAX_MEM; tmp++) {
if (tdev->res.mem_resource[tmp].flags & IORESOURCE_MEM) {
+ if (pnp_mem_flags(dev, tmp) & IORESOURCE_DISABLED)
+ continue;
taddr = &tdev->res.mem_resource[tmp].start;
tend = &tdev->res.mem_resource[tmp].end;
if (ranged_conflict(addr,end,taddr,tend))
@@ -409,6 +413,8 @@ int pnp_check_irq(struct pnp_dev * dev, int idx)
continue;
for (tmp = 0; tmp < PNP_MAX_IRQ; tmp++) {
if (tdev->res.irq_resource[tmp].flags & IORESOURCE_IRQ) {
+ if (pnp_irq_flags(dev, tmp) & IORESOURCE_DISABLED)
+ continue;
if ((tdev->res.irq_resource[tmp].start == *irq))
return 0;
}
@@ -462,6 +468,8 @@ int pnp_check_dma(struct pnp_dev * dev, int idx)
continue;
for (tmp = 0; tmp < PNP_MAX_DMA; tmp++) {
if (tdev->res.dma_resource[tmp].flags & IORESOURCE_DMA) {
+ if (pnp_dma_flags(dev, tmp) & IORESOURCE_DISABLED)
+ continue;
if ((tdev->res.dma_resource[tmp].start == *dma))
return 0;
}
diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c
index af359e092ed0..375aa2172239 100644
--- a/drivers/pnp/support.c
+++ b/drivers/pnp/support.c
@@ -68,9 +68,13 @@ static void current_irqresource(struct pnp_resource_table * res, int irq)
int i = 0;
while ((res->irq_resource[i].flags & IORESOURCE_IRQ) && i < PNP_MAX_IRQ) i++;
if (i < PNP_MAX_IRQ) {
+ res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+ if (irq == -1) {
+ res->irq_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
+ }
res->irq_resource[i].start =
res->irq_resource[i].end = (unsigned long) irq;
- res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
}
}
@@ -79,9 +83,13 @@ static void current_dmaresource(struct pnp_resource_table * res, int dma)
int i = 0;
while ((res->dma_resource[i].flags & IORESOURCE_DMA) && i < PNP_MAX_DMA) i++;
if (i < PNP_MAX_DMA) {
+ res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
+ if (dma == -1) {
+ res->dma_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
+ }
res->dma_resource[i].start =
res->dma_resource[i].end = (unsigned long) dma;
- res->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
}
}
@@ -90,9 +98,13 @@ static void current_ioresource(struct pnp_resource_table * res, int io, int len)
int i = 0;
while ((res->port_resource[i].flags & IORESOURCE_IO) && i < PNP_MAX_PORT) i++;
if (i < PNP_MAX_PORT) {
+ res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
+ if (len <= 0 || (io + len -1) >= 0x10003) {
+ res->port_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
+ }
res->port_resource[i].start = (unsigned long) io;
res->port_resource[i].end = (unsigned long)(io + len - 1);
- res->port_resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
}
}
@@ -101,9 +113,13 @@ static void current_memresource(struct pnp_resource_table * res, int mem, int le
int i = 0;
while ((res->mem_resource[i].flags & IORESOURCE_MEM) && i < PNP_MAX_MEM) i++;
if (i < PNP_MAX_MEM) {
+ res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
+ if (len <= 0) {
+ res->mem_resource[i].flags |= IORESOURCE_DISABLED;
+ return;
+ }
res->mem_resource[i].start = (unsigned long) mem;
res->mem_resource[i].end = (unsigned long)(mem + len - 1);
- res->mem_resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
}
}
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index af35f91fe3b2..633c9a028e29 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -582,7 +582,7 @@ void scsi_done(struct scsi_cmnd *cmd)
local_irq_save(flags);
cpu = smp_processor_id();
list_add_tail(&cmd->eh_entry, &done_q[cpu]);
- cpu_raise_softirq(cpu, SCSI_SOFTIRQ);
+ raise_softirq_irqoff(SCSI_SOFTIRQ);
local_irq_restore(flags);
}
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 5f9307658f4c..6720dd216fdc 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -646,7 +646,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
sdev->max_device_blocked = SCSI_DEFAULT_DEVICE_BLOCKED;
sdev->use_10_for_rw = 1;
- sdev->use_10_for_ms = 1;
+ sdev->use_10_for_ms = 0;
if(sdev->host->hostt->slave_configure)
sdev->host->hostt->slave_configure(sdev);
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index 7ff8ff5dbecc..f212ae0992d1 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -1533,7 +1533,6 @@ void unregister_serial(int line)
}
module_init(rs68328_init);
-/* DAVIDM module_exit(rs68328_fini); */
diff --git a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c
index b1e012cb5d3d..a70c3ddfadfa 100644
--- a/drivers/serial/8250_cs.c
+++ b/drivers/serial/8250_cs.c
@@ -133,7 +133,7 @@ static dev_link_t *dev_list = NULL;
static void serial_remove(dev_link_t *link)
{
struct serial_info *info = link->priv;
- int i, ret;
+ int i;
link->state &= ~DEV_PRESENT;
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index 38bcb8765456..c6b7caa224df 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -1643,7 +1643,6 @@ mcfrs_init(void)
}
module_init(mcfrs_init);
-/* DAVIDM module_exit(mcfrs_fini); */
/****************************************************************************/
/* Serial Console */
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h
index f4fde1c2310a..6e4a1b3a4e15 100644
--- a/fs/adfs/adfs.h
+++ b/fs/adfs/adfs.h
@@ -88,7 +88,7 @@ void __adfs_error(struct super_block *sb, const char *function,
#define adfs_error(sb, fmt...) __adfs_error(sb, __FUNCTION__, fmt)
/* namei.c */
-extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
/* super.c */
diff --git a/fs/adfs/dir.c b/fs/adfs/dir.c
index df29ce99c6ed..aae5b4e066db 100644
--- a/fs/adfs/dir.c
+++ b/fs/adfs/dir.c
@@ -269,7 +269,7 @@ struct dentry_operations adfs_dentry_operations = {
.d_compare = adfs_compare,
};
-struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
struct object_info obj;
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 01defe3d0ff8..f2cbba3b7578 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -210,7 +210,7 @@ affs_find_entry(struct inode *dir, struct dentry *dentry)
}
struct dentry *
-affs_lookup(struct inode *dir, struct dentry *dentry)
+affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
@@ -256,7 +256,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
}
int
-affs_create(struct inode *dir, struct dentry *dentry, int mode)
+affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct inode *inode;
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 12effcc6f896..a63e3e9679fe 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -23,10 +23,10 @@
#include "super.h"
#include "internal.h"
-static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry);
+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
static int afs_dir_open(struct inode *inode, struct file *file);
static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir);
-static int afs_d_revalidate(struct dentry *dentry, int flags);
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *);
static int afs_d_delete(struct dentry *dentry);
static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos,
ino_t ino, unsigned dtype);
@@ -414,7 +414,7 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, lof
/*
* look up an entry in a directory
*/
-static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct afs_dir_lookup_cookie cookie;
struct afs_super_info *as;
@@ -487,7 +487,7 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry)
* - NOTE! the hit can be a negative hit too, so we can't assume we have an inode
* (derived from nfs_lookup_revalidate)
*/
-static int afs_d_revalidate(struct dentry *dentry, int flags)
+static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct afs_dir_lookup_cookie cookie;
struct dentry *parent;
@@ -495,7 +495,7 @@ static int afs_d_revalidate(struct dentry *dentry, int flags)
unsigned fpos;
int ret;
- _enter("%s,%x",dentry->d_name.name,flags);
+ _enter("%s,%p",dentry->d_name.name,nd);
parent = dget_parent(dentry);
dir = parent->d_inode;
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c
index 0279fcbf8329..d22887d47f38 100644
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -21,7 +21,7 @@
#include "internal.h"
-static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry);
+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
static int afs_mntpt_open(struct inode *inode, struct file *file);
struct file_operations afs_mntpt_file_operations = {
@@ -93,7 +93,7 @@ int afs_mntpt_check_symlink(afs_vnode_t *vnode)
/*
* no valid lookup procedure on this sort of dir
*/
-static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
return ERR_PTR(-EREMOTE);
} /* end afs_mntpt_lookup() */
diff --git a/fs/aio.c b/fs/aio.c
index ccbdeede79ff..58983f34337f 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -552,7 +552,7 @@ static void unuse_mm(struct mm_struct *mm)
{
current->mm = NULL;
/* active_mm is still 'mm' */
- enter_lazy_tlb(mm, current, smp_processor_id());
+ enter_lazy_tlb(mm, current);
}
/* Run on kevent's context. FIXME: needs to be per-cpu and warn if an
diff --git a/fs/attr.c b/fs/attr.c
index 0d9e778fb5d3..2048b99a112c 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -22,8 +22,6 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
int retval = -EPERM;
unsigned int ia_valid = attr->ia_valid;
- lock_kernel();
-
/* If force is set do it anyway. */
if (ia_valid & ATTR_FORCE)
goto fine;
@@ -58,7 +56,6 @@ int inode_change_ok(struct inode *inode, struct iattr *attr)
fine:
retval = 0;
error:
- unlock_kernel();
return retval;
}
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index e6e3b0c468d7..546ac2f9af87 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -18,7 +18,7 @@
#include "autofs_i.h"
static int autofs_root_readdir(struct file *,void *,filldir_t);
-static struct dentry *autofs_root_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs_root_lookup(struct inode *,struct dentry *, struct nameidata *);
static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
static int autofs_root_unlink(struct inode *,struct dentry *);
static int autofs_root_rmdir(struct inode *,struct dentry *);
@@ -144,7 +144,7 @@ static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, str
* yet completely filled in, and revalidate has to delay such
* lookups..
*/
-static int autofs_revalidate(struct dentry * dentry, int flags)
+static int autofs_revalidate(struct dentry * dentry, struct nameidata *nd)
{
struct inode * dir;
struct autofs_sb_info *sbi;
@@ -195,7 +195,7 @@ static struct dentry_operations autofs_dentry_operations = {
.d_revalidate = autofs_revalidate,
};
-static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct autofs_sb_info *sbi;
int oz_mode;
@@ -230,7 +230,7 @@ static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentr
d_add(dentry, NULL);
up(&dir->i_sem);
- autofs_revalidate(dentry, 0);
+ autofs_revalidate(dentry, nd);
down(&dir->i_sem);
/*
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index de61c25779c1..49f9f4d3b406 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -18,13 +18,13 @@
#include <linux/smp_lock.h>
#include "autofs_i.h"
-static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *, struct nameidata *);
static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
static int autofs4_dir_unlink(struct inode *,struct dentry *);
static int autofs4_dir_rmdir(struct inode *,struct dentry *);
static int autofs4_dir_mkdir(struct inode *,struct dentry *,int);
static int autofs4_root_ioctl(struct inode *, struct file *,unsigned int,unsigned long);
-static struct dentry *autofs4_root_lookup(struct inode *,struct dentry *);
+static struct dentry *autofs4_root_lookup(struct inode *,struct dentry *, struct nameidata *);
struct file_operations autofs4_root_operations = {
.open = dcache_dir_open,
@@ -143,7 +143,7 @@ static int try_to_fill_dentry(struct dentry *dentry,
* yet completely filled in, and revalidate has to delay such
* lookups..
*/
-static int autofs4_root_revalidate(struct dentry * dentry, int flags)
+static int autofs4_root_revalidate(struct dentry * dentry, struct nameidata *nd)
{
struct inode * dir = dentry->d_parent->d_inode;
struct autofs_sb_info *sbi = autofs4_sbi(dir->i_sb);
@@ -183,7 +183,7 @@ static int autofs4_root_revalidate(struct dentry * dentry, int flags)
return 1;
}
-static int autofs4_revalidate(struct dentry *dentry, int flags)
+static int autofs4_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
@@ -225,7 +225,7 @@ static struct dentry_operations autofs4_dentry_operations = {
/* Lookups in non-root dirs never find anything - if it's there, it's
already in the dcache */
/* SMP-safe */
-static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
#if 0
DPRINTK(("autofs_dir_lookup: ignoring lookup of %.*s/%.*s\n",
@@ -239,7 +239,7 @@ static struct dentry *autofs4_dir_lookup(struct inode *dir, struct dentry *dentr
}
/* Lookups in the root directory */
-static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct autofs_sb_info *sbi;
int oz_mode;
@@ -276,7 +276,7 @@ static struct dentry *autofs4_root_lookup(struct inode *dir, struct dentry *dent
if (dentry->d_op && dentry->d_op->d_revalidate) {
up(&dir->i_sem);
- (dentry->d_op->d_revalidate)(dentry, 0);
+ (dentry->d_op->d_revalidate)(dentry, nd);
down(&dir->i_sem);
}
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c
index 4fb5a163e50d..d7846d65b361 100644
--- a/fs/befs/linuxvfs.c
+++ b/fs/befs/linuxvfs.c
@@ -33,7 +33,7 @@ static int befs_readdir(struct file *, void *, filldir_t);
static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
static int befs_readpage(struct file *file, struct page *page);
static sector_t befs_bmap(struct address_space *mapping, sector_t block);
-static struct dentry *befs_lookup(struct inode *, struct dentry *);
+static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *);
static void befs_read_inode(struct inode *ino);
static struct inode *befs_alloc_inode(struct super_block *sb);
static void befs_destroy_inode(struct inode *inode);
@@ -163,7 +163,7 @@ befs_get_block(struct inode *inode, sector_t block,
}
static struct dentry *
-befs_lookup(struct inode *dir, struct dentry *dentry)
+befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
struct super_block *sb = dir->i_sb;
diff --git a/fs/bfs/dir.c b/fs/bfs/dir.c
index 386f5fff4a77..7e5b4781eb25 100644
--- a/fs/bfs/dir.c
+++ b/fs/bfs/dir.c
@@ -78,7 +78,8 @@ struct file_operations bfs_dir_operations = {
extern void dump_imap(const char *, struct super_block *);
-static int bfs_create(struct inode * dir, struct dentry * dentry, int mode)
+static int bfs_create(struct inode * dir, struct dentry * dentry, int mode,
+ struct nameidata *nd)
{
int err;
struct inode * inode;
@@ -127,7 +128,7 @@ static int bfs_create(struct inode * dir, struct dentry * dentry, int mode)
return 0;
}
-static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry * bfs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
struct inode * inode = NULL;
struct buffer_head * bh;
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 1c7699cea914..4cdc1b8c5020 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -1,15 +1,17 @@
+/****************************************************************************/
/*
* linux/fs/binfmt_flat.c
*
- * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@uclinux.org>
+ * Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com>
* Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com>
- *
+ * Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com>
+ * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com>
* based heavily on:
*
* linux/fs/binfmt_aout.c:
* Copyright (C) 1991, 1992, 1996 Linus Torvalds
* linux/fs/binfmt_flat.c for 2.0 kernel
- * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
+ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
* JAN/99 -- coded full program relocation (gerg@snapgear.com)
*/
@@ -42,27 +44,69 @@
#include <asm/unaligned.h>
#include <asm/cacheflush.h>
-#undef DEBUG
+/****************************************************************************/
+
+#if 0
+#define DEBUG 1
+#endif
+
#ifdef DEBUG
-#define DBG_FLT(a...) printk(##a)
+#define DBG_FLT(a...) printk(a)
#else
#define DBG_FLT(a...)
#endif
+#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
+#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
+
+struct lib_info {
+ struct {
+ unsigned long start_code; /* Start of text segment */
+ unsigned long start_data; /* Start of data segment */
+ unsigned long start_brk; /* End of data segment */
+ unsigned long text_len; /* Length of text segment */
+ unsigned long entry; /* Start address for this module */
+ unsigned long build_date; /* When this one was compiled */
+ short loaded; /* Has this library been loaded? */
+ } lib_list[MAX_SHARED_LIBS];
+};
+
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+static int load_flat_shared_library(int id, struct lib_info *p);
+#endif
+
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
-static int load_flat_library(struct file*);
+static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file);
+
extern void dump_thread(struct pt_regs *, struct user *);
static struct linux_binfmt flat_format = {
- NULL, THIS_MODULE, load_flat_binary, load_flat_library, NULL, PAGE_SIZE
+ .module = THIS_MODULE,
+ .load_binary = load_flat_binary,
+ .core_dump = flat_core_dump,
+ .min_coredump = PAGE_SIZE
};
+/****************************************************************************/
+/*
+ * Routine writes a core dump image in the current directory.
+ * Currently only a stub-function.
+ */
+
+static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file)
+{
+ printk("Process %s:%d received signr %d and should have core dumped\n",
+ current->comm, current->pid, (int) signr);
+ return(1);
+}
+/****************************************************************************/
/*
* create_flat_tables() parses the env- and arg-strings in new user
* memory and creates the pointer tables from them, and puts their
* addresses on the "stack", returning the new stack pointer value.
*/
+
static unsigned long create_flat_tables(
unsigned long pp,
struct linux_binprm * bprm)
@@ -80,10 +124,13 @@ static unsigned long create_flat_tables(
envp = sp;
sp -= argc+1;
argv = sp;
+
+ flat_stack_align(sp);
if (flat_argvp_envp_on_stack()) {
- put_user((unsigned long) envp, --sp);
- put_user((unsigned long) argv, --sp);
+ --sp; put_user((unsigned long) envp, sp);
+ --sp; put_user((unsigned long) argv, sp);
}
+
put_user(argc,--sp);
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
@@ -105,6 +152,7 @@ static unsigned long create_flat_tables(
return (unsigned long)sp;
}
+/****************************************************************************/
#ifdef CONFIG_BINFMT_ZFLAT
@@ -183,7 +231,7 @@ static int decompress_exec(
if (buf[3] & EXTRA_FIELD) {
ret += 2 + buf[10] + (buf[11] << 8);
if (unlikely(LBUFSIZE == ret)) {
- DBG_FLAT("binfmt_flat: buffer overflow (EXTRA)?\n");
+ DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
return -ENOEXEC;
}
}
@@ -191,7 +239,7 @@ static int decompress_exec(
for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
;
if (unlikely(LBUFSIZE == ret)) {
- DBG_FLAT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
+ DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
return -ENOEXEC;
}
}
@@ -199,7 +247,7 @@ static int decompress_exec(
for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
;
if (unlikely(LBUFSIZE == ret)) {
- DBG_FLAT("binfmt_flat: buffer overflow (COMMENT)?\n");
+ DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
return -ENOEXEC;
}
}
@@ -243,48 +291,78 @@ static int decompress_exec(
#endif /* CONFIG_BINFMT_ZFLAT */
+/****************************************************************************/
static unsigned long
-calc_reloc(unsigned long r, unsigned long text_len)
+calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp)
{
unsigned long addr;
-
- if (r > current->mm->start_brk - current->mm->start_data + text_len) {
- printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x), killing!\n",
- (int) r,(int)(current->mm->start_brk-current->mm->start_code));
- send_sig(SIGSEGV, current, 0);
- return(current->mm->start_brk); /* return something safe to write to */
+ int id;
+ unsigned long start_brk;
+ unsigned long start_data;
+ unsigned long text_len;
+ unsigned long start_code;
+
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+ if (r == 0)
+ id = curid; /* Relocs of 0 are always self referring */
+ else {
+ id = (r >> 24) & 0xff; /* Find ID for this reloc */
+ r &= 0x00ffffff; /* Trim ID off here */
+ }
+ if (id >= MAX_SHARED_LIBS) {
+ printk("BINFMT_FLAT: reference 0x%x to shared library %d",
+ (unsigned) r, id);
+ goto failed;
+ }
+ if (curid != id) {
+ if (internalp) {
+ printk("BINFMT_FLAT: reloc address 0x%x not in same module "
+ "(%d != %d)", (unsigned) r, curid, id);
+ goto failed;
+ } else if ( ! p->lib_list[id].loaded &&
+ load_flat_shared_library(id, p) > (unsigned long) -4096) {
+ printk("BINFMT_FLAT: failed to load library %d", id);
+ goto failed;
+ }
+ /* Check versioning information (i.e. time stamps) */
+ if (p->lib_list[id].build_date && p->lib_list[curid].build_date &&
+ p->lib_list[curid].build_date < p->lib_list[id].build_date) {
+ printk("BINFMT_FLAT: library %d is younger than %d", id, curid);
+ goto failed;
+ }
}
+#else
+ id = 0;
+#endif
- if (r < text_len) {
- /* In text segment */
- return r + current->mm->start_code;
+ start_brk = p->lib_list[id].start_brk;
+ start_data = p->lib_list[id].start_data;
+ start_code = p->lib_list[id].start_code;
+ text_len = p->lib_list[id].text_len;
+
+ if (!flat_reloc_valid(r, start_brk - start_data + text_len)) {
+ printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)",
+ (int) r,(int)(start_brk-start_code),(int)text_len);
+ goto failed;
}
- /*
- * we allow inclusive ranges here so that programs may do things
- * like reference the end of data (_end) without failing these tests
- */
- addr = r - text_len + current->mm->start_data;
- if (addr >= current->mm->start_code &&
- addr <= current->mm->start_code + text_len)
- return(addr);
-
- if (addr >= current->mm->start_data &&
- addr <= current->mm->start_brk)
- return(addr);
-
- printk("BINFMT_FLAT: reloc addr outside text/data 0x%x "
- "code(0x%x - 0x%x) data(0x%x - 0x%x) killing\n", (int) addr,
- (int) current->mm->start_code,
- (int) (current->mm->start_code + text_len),
- (int) current->mm->start_data,
- (int) current->mm->start_brk);
+ if (r < text_len) /* In text segment */
+ addr = r + start_code;
+ else /* In data segment */
+ addr = r - text_len + start_data;
+
+ /* Range checked already above so doing the range tests is redundant...*/
+ return(addr);
+
+failed:
+ printk(", killing %s!\n", current->comm);
send_sig(SIGSEGV, current, 0);
- return(current->mm->start_brk); /* return something safe to write to */
+ return RELOC_FAILED;
}
+/****************************************************************************/
void old_reloc(unsigned long rl)
{
@@ -327,26 +405,22 @@ void old_reloc(unsigned long rl)
#endif
}
+/****************************************************************************/
-/*
- * These are the functions used to load flat style executables and shared
- * libraries. There is no binary dependent code anywhere else.
- */
-
-static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+static int load_flat_file(struct linux_binprm * bprm,
+ struct lib_info *libinfo, int id, unsigned long *extra_stack)
{
struct flat_hdr * hdr;
unsigned long textpos = 0, datapos = 0, result;
+ unsigned long realdatastart = 0;
unsigned long text_len, data_len, bss_len, stack_len, flags;
- unsigned long memp = 0, memkasked = 0; /* for finding the brk area */
+ unsigned long memp = 0; /* for finding the brk area */
unsigned long extra, rlim;
- unsigned long p = bprm->p;
unsigned long *reloc = 0, *rp;
struct inode *inode;
int i, rev, relocs = 0;
loff_t fpos;
-
- DBG_FLT("BINFMT_FLAT: Loading file: %x\n", bprm->file);
+ unsigned long start_code, end_code;
hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */
inode = bprm->file->f_dentry->d_inode;
@@ -355,41 +429,42 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start);
bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end);
stack_len = ntohl(hdr->stack_size);
+ if (extra_stack) {
+ stack_len += *extra_stack;
+ *extra_stack = stack_len;
+ }
relocs = ntohl(hdr->reloc_count);
flags = ntohl(hdr->flags);
rev = ntohl(hdr->rev);
- /*
- * We have to add the size of our arguments to our stack size
- * otherwise it's too easy for users to create stack overflows
- * by passing in a huge argument list. And yes, we have to be
- * pedantic and include space for the argv/envp array as it may have
- * a lot of entries.
- */
- #define TOP_OF_ARGS (PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *))
- stack_len += TOP_OF_ARGS - bprm->p; /* the strings */
- stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
- stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
+ if (flags & FLAT_FLAG_KTRACE)
+ printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename);
if (strncmp(hdr->magic, "bFLT", 4) ||
(rev != FLAT_VERSION && rev != OLD_FLAT_VERSION)) {
/*
* because a lot of people do not manage to produce good
* flat binaries, we leave this printk to help them realise
- * the problem. We only print the error if it's
- * not a script file.
+ * the problem. We only print the error if its not a script file
*/
if (strncmp(hdr->magic, "#!", 2))
printk("BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n",
rev, (int) FLAT_VERSION);
return -ENOEXEC;
}
+
+ /* Don't allow old format executables to use shared libraries */
+ if (rev == OLD_FLAT_VERSION && id != 0) {
+ printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n",
+ (int) FLAT_VERSION);
+ return -ENOEXEC;
+ }
/*
* fix up the flags for the older format, there were all kinds
* of endian hacks, this only works for the simple cases
*/
- if (rev == OLD_FLAT_VERSION && flags)
+ if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
flags = FLAT_FLAG_RAM;
#ifndef CONFIG_BINFMT_ZFLAT
@@ -411,15 +486,22 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return -ENOMEM;
/* Flush all traces of the currently running executable */
- result = flush_old_exec(bprm);
- if (result)
- return result;
+ if (id == 0) {
+ result = flush_old_exec(bprm);
+ if (result)
+ return result;
+
+ /* OK, This is the point of no return */
+ set_personality(PER_LINUX);
+ }
- /* OK, This is the point of no return */
- set_personality(PER_LINUX);
+ /*
+ * calculate the extra space we need to map in
+ */
+ extra = max(bss_len + stack_len, relocs * sizeof(unsigned long));
/*
- * there are a couple of cases here, the separate code/data
+ * there are a couple of cases here, the seperate code/data
* case, and then the fully copied to RAM case which lumps
* it all together.
*/
@@ -437,26 +519,27 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
if (!textpos)
textpos = (unsigned long) -ENOMEM;
printk("Unable to mmap process text, errno %d\n", (int)-textpos);
+ return(textpos);
}
- extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)),
-
down_write(&current->mm->mmap_sem);
- datapos = do_mmap(0, 0, data_len + extra,
+ realdatastart = do_mmap(0, 0, data_len + extra +
+ MAX_SHARED_LIBS * sizeof(unsigned long),
PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
up_write(&current->mm->mmap_sem);
- if (datapos == 0 || datapos >= (unsigned long)-4096) {
- if (!datapos)
- datapos = (unsigned long) -ENOMEM;
+ if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
+ if (!realdatastart)
+ realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
(int)-datapos);
do_munmap(current->mm, textpos, text_len);
- return datapos;
+ return realdatastart;
}
+ datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n",
- data_len + bss_len + stack_len, datapos);
+ (int)(data_len + bss_len + stack_len), (int)datapos);
fpos = ntohl(hdr->data_start);
#ifdef CONFIG_BINFMT_ZFLAT
@@ -466,30 +549,24 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
} else
#endif
{
- result = bprm->file->f_op->read(bprm->file,
- (char *) datapos, data_len + extra, &fpos);
+ result = bprm->file->f_op->read(bprm->file, (char *) datapos,
+ data_len + (relocs * sizeof(unsigned long)), &fpos);
}
if (result >= (unsigned long)-4096) {
printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len);
- do_munmap(current->mm, datapos, data_len + extra);
+ do_munmap(current->mm, realdatastart, data_len + extra);
return result;
}
reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len));
- memp = datapos;
- memkasked = data_len + extra;
+ memp = realdatastart;
} else {
- /*
- * calculate the extra space we need to map in
- */
-
- extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)),
-
down_write(&current->mm->mmap_sem);
- textpos = do_mmap(0, 0, text_len + data_len + extra,
+ textpos = do_mmap(0, 0, text_len + data_len + extra +
+ MAX_SHARED_LIBS * sizeof(unsigned long),
PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
@@ -497,12 +574,14 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
textpos = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process text/data, errno %d\n",
(int)-textpos);
+ return(textpos);
}
- datapos = textpos + ntohl (hdr->data_start);
- reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start));
+ realdatastart = textpos + ntohl(hdr->data_start);
+ datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
+ reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) +
+ MAX_SHARED_LIBS * sizeof(unsigned long));
memp = textpos;
- memkasked = text_len + data_len + extra;
#ifdef CONFIG_BINFMT_ZFLAT
/*
@@ -514,6 +593,8 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
(text_len + data_len + (relocs * sizeof(unsigned long))
- sizeof (struct flat_hdr)),
0);
+ memmove((void *) datapos, (void *) realdatastart,
+ data_len + (relocs * sizeof(unsigned long)));
} else if (flags & FLAT_FLAG_GZDATA) {
fpos = 0;
result = bprm->file->f_op->read(bprm->file,
@@ -527,40 +608,64 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
{
fpos = 0;
result = bprm->file->f_op->read(bprm->file,
- (char *) textpos, text_len + data_len + extra, &fpos);
+ (char *) textpos, text_len, &fpos);
+ if (result < (unsigned long) -4096) {
+ fpos = ntohl(hdr->data_start);
+ result = bprm->file->f_op->read(bprm->file, (char *) datapos,
+ data_len + (relocs * sizeof(unsigned long)), &fpos);
+ }
}
if (result >= (unsigned long)-4096) {
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
- do_munmap(current->mm, textpos, text_len + data_len + extra);
+ do_munmap(current->mm, textpos, text_len + data_len + extra +
+ MAX_SHARED_LIBS * sizeof(unsigned long));
return result;
}
}
- DBG_FLT("Mapping is %x, Entry point is %x, data_start is %x\n",
- textpos, ntohl(hdr->entry), ntohl(hdr->data_start));
-
- current->mm->start_code = textpos + sizeof (struct flat_hdr);
- current->mm->end_code = textpos + text_len;
- current->mm->start_data = datapos;
- current->mm->end_data = datapos + data_len;
- /*
- * set up the brk stuff (uses any slack left in data/bss/stack allocation
- * We put the brk after the bss (between the bss and stack) like other
- * platforms.
- */
- current->mm->start_brk = datapos + data_len + bss_len;
- current->mm->brk = (current->mm->start_brk + 3) & ~3;
- current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
- current->mm->rss = 0;
+ if (flags & FLAT_FLAG_KTRACE)
+ printk("Mapping is %x, Entry point is %x, data_start is %x\n",
+ (int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start));
+
+ /* The main program needs a little extra setup in the task structure */
+ start_code = textpos + sizeof (struct flat_hdr);
+ end_code = textpos + text_len;
+ if (id == 0) {
+ current->mm->start_code = start_code;
+ current->mm->end_code = end_code;
+ current->mm->start_data = datapos;
+ current->mm->end_data = datapos + data_len;
+ /*
+ * set up the brk stuff, uses any slack left in data/bss/stack
+ * allocation. We put the brk after the bss (between the bss
+ * and stack) like other platforms.
+ */
+ current->mm->start_brk = datapos + data_len + bss_len;
+ current->mm->brk = (current->mm->start_brk + 3) & ~3;
+ current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len;
+ current->mm->rss = 0;
+ }
- DBG_FLT("Load %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
- bprm->filename,
- (int) current->mm->start_code, (int) current->mm->end_code,
- (int) current->mm->start_data, (int) current->mm->end_data,
- (int) current->mm->end_data, (int) current->mm->brk);
+ if (flags & FLAT_FLAG_KTRACE)
+ printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n",
+ id ? "Lib" : "Load", bprm->filename,
+ (int) start_code, (int) end_code,
+ (int) datapos,
+ (int) (datapos + data_len),
+ (int) (datapos + data_len),
+ (int) (((datapos + data_len + bss_len) + 3) & ~3));
text_len -= sizeof(struct flat_hdr); /* the real code len */
+ /* Store the current module values into the global library structure */
+ libinfo->lib_list[id].start_code = start_code;
+ libinfo->lib_list[id].start_data = datapos;
+ libinfo->lib_list[id].start_brk = datapos + data_len + bss_len;
+ libinfo->lib_list[id].text_len = text_len;
+ libinfo->lib_list[id].loaded = 1;
+ libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
+ libinfo->lib_list[id].build_date = ntohl(hdr->build_date);
+
/*
* We just load the allocations into some temporary memory to
* help simplify all this mumbo jumbo
@@ -573,10 +678,16 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* really an offset into the image which contains an offset into the
* image.
*/
-
if (flags & FLAT_FLAG_GOTPIC) {
- for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++)
- *rp = calc_reloc(*rp, text_len);
+ for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) {
+ unsigned long addr;
+ if (*rp) {
+ addr = calc_reloc(*rp, libinfo, id, 0);
+ if (addr == RELOC_FAILED)
+ return -ENOEXEC;
+ *rp = addr;
+ }
+ }
}
/*
@@ -590,63 +701,172 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* reference to be statically initialised to _stext (I've moved
* __start to address 4 so that is okay).
*/
-
if (rev > OLD_FLAT_VERSION) {
for (i=0; i < relocs; i++) {
- unsigned long addr;
+ unsigned long addr, relval;
/* Get the address of the pointer to be
relocated (of course, the address has to be
relocated first). */
- rp = (unsigned long *) calc_reloc(ntohl(reloc[i]), text_len);
+ relval = ntohl(reloc[i]);
+ addr = flat_get_relocate_addr(relval);
+ rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1);
+ if (rp == (unsigned long *)RELOC_FAILED)
+ return -ENOEXEC;
/* Get the pointer's value. */
- addr = get_unaligned (rp);
-
+ addr = flat_get_addr_from_rp(rp, relval);
if (addr != 0) {
/*
* Do the relocation. PIC relocs in the data section are
* already in target order
*/
- addr = calc_reloc(
- (flags & FLAT_FLAG_GOTPIC) ? addr : ntohl(addr),
- text_len);
+ if ((flags & FLAT_FLAG_GOTPIC) == 0)
+ addr = ntohl(addr);
+ addr = calc_reloc(addr, libinfo, id, 0);
+ if (addr == RELOC_FAILED)
+ return -ENOEXEC;
+
/* Write back the relocated pointer. */
- put_unaligned (addr, rp);
+ flat_put_addr_at_rp(rp, addr, relval);
}
}
} else {
for (i=0; i < relocs; i++)
old_reloc(ntohl(reloc[i]));
}
+
+ flush_icache_range(start_code, end_code);
/* zero the BSS, BRK and stack areas */
memset((void*)(datapos + data_len), 0, bss_len +
- (current->mm->context.end_brk - current->mm->start_brk) +
+ (memp + ksize((void *) memp) - stack_len - /* end brk */
+ libinfo->lib_list[id].start_brk) + /* start brk */
stack_len);
+ return 0;
+}
+
+
+/****************************************************************************/
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+
+/*
+ * Load a shared library into memory. The library gets its own data
+ * segment (including bss) but not argv/argc/environ.
+ */
+
+static int load_flat_shared_library(int id, struct lib_info *libs)
+{
+ struct linux_binprm bprm;
+ int res;
+ char buf[16];
+
+ /* Create the file name */
+ sprintf(buf, "/lib/lib%d.so", id);
+
+ /* Open the file up */
+ bprm.filename = buf;
+ bprm.file = open_exec(bprm.filename);
+ res = PTR_ERR(bprm.file);
+ if (IS_ERR(bprm.file))
+ return res;
+
+ res = prepare_binprm(&bprm);
+
+ if (res <= (unsigned long)-4096)
+ res = load_flat_file(&bprm, libs, id, NULL);
+ if (bprm.file) {
+ allow_write_access(bprm.file);
+ fput(bprm.file);
+ bprm.file = NULL;
+ }
+ return(res);
+}
+
+#endif /* CONFIG_BINFMT_SHARED_FLAT */
+/****************************************************************************/
+
+/*
+ * These are the functions used to load flat style executables and shared
+ * libraries. There is no binary dependent code anywhere else.
+ */
+
+static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
+{
+ struct lib_info libinfo;
+ unsigned long p = bprm->p;
+ unsigned long stack_len;
+ unsigned long start_addr;
+ unsigned long *sp;
+ int res;
+ int i, j;
+
+ memset(&libinfo, 0, sizeof(libinfo));
+ /*
+ * We have to add the size of our arguments to our stack size
+ * otherwise it's too easy for users to create stack overflows
+ * by passing in a huge argument list. And yes, we have to be
+ * pedantic and include space for the argv/envp array as it may have
+ * a lot of entries.
+ */
+#define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
+ stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
+ stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */
+ stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */
+
+
+ res = load_flat_file(bprm, &libinfo, 0, &stack_len);
+ if (res > (unsigned long)-4096)
+ return res;
+
+ /* Update data segment pointers for all libraries */
+ for (i=0; i<MAX_SHARED_LIBS; i++)
+ if (libinfo.lib_list[i].loaded)
+ for (j=0; j<MAX_SHARED_LIBS; j++)
+ (-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] =
+ (libinfo.lib_list[j].loaded)?
+ libinfo.lib_list[j].start_data:UNLOADED_LIB;
+
compute_creds(bprm);
current->flags &= ~PF_FORKNOEXEC;
- flush_icache_range(current->mm->start_code, current->mm->end_code);
-
set_binfmt(&flat_format);
p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4;
- DBG_FLT("p=%x\n", p);
+ DBG_FLT("p=%x\n", (int)p);
/* copy the arg pages onto the stack, this could be more efficient :-) */
for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--)
* (char *) --p =
((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE];
- current->mm->start_stack = (unsigned long) create_flat_tables(p, bprm);
+ sp = (unsigned long *) create_flat_tables(p, bprm);
+
+ /* Fake some return addresses to ensure the call chain will
+ * initialise library in order for us. We are required to call
+ * lib 1 first, then 2, ... and finally the main program (id 0).
+ */
+ start_addr = libinfo.lib_list[0].entry;
+
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+ for (i = MAX_SHARED_LIBS-1; i>0; i--) {
+ if (libinfo.lib_list[i].loaded) {
+ /* Push previos first to call address */
+ --sp; put_user(start_addr, sp);
+ start_addr = libinfo.lib_list[i].entry;
+ }
+ }
+#endif
+
+ /* Stash our initial stack pointer into the mm structure */
+ current->mm->start_stack = (unsigned long )sp;
+
DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n",
- regs, textpos + ntohl(hdr->entry), current->mm->start_stack);
- start_thread(regs,
- textpos + ntohl(hdr->entry),
- current->mm->start_stack);
+ (int)regs, (int)start_addr, (int)current->mm->start_stack);
+
+ start_thread(regs, start_addr, current->mm->start_stack);
if (current->ptrace & PT_PTRACED)
send_sig(SIGTRAP, current, 0);
@@ -654,10 +874,7 @@ static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
return 0;
}
-static int load_flat_library(struct file *file)
-{
- return(-ENOEXEC);
-}
+/****************************************************************************/
static int __init init_flat_binfmt(void)
{
@@ -669,5 +886,9 @@ static void __exit exit_flat_binfmt(void)
unregister_binfmt(&flat_format);
}
+/****************************************************************************/
+
module_init(init_flat_binfmt);
module_exit(exit_flat_binfmt);
+
+/****************************************************************************/
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 52e956455310..74db58a40025 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -155,11 +155,13 @@ static int blkdev_commit_write(struct file *file, struct page *page, unsigned fr
*/
static loff_t block_llseek(struct file *file, loff_t offset, int origin)
{
- /* ewww */
- loff_t size = file->f_dentry->d_inode->i_bdev->bd_inode->i_size;
+ struct inode *bd_inode;
+ loff_t size;
loff_t retval;
- lock_kernel();
+ bd_inode = file->f_dentry->d_inode->i_bdev->bd_inode;
+ down(&bd_inode->i_sem);
+ size = bd_inode->i_size;
switch (origin) {
case 2:
@@ -175,7 +177,7 @@ static loff_t block_llseek(struct file *file, loff_t offset, int origin)
}
retval = offset;
}
- unlock_kernel();
+ up(&bd_inode->i_sem);
return retval;
}
diff --git a/fs/buffer.c b/fs/buffer.c
index 56c9f4e03bdd..d3fbedea7a1a 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -319,6 +319,7 @@ asmlinkage long sys_fsync(unsigned int fd)
/* We need to protect against concurrent writers.. */
down(&inode->i_sem);
+ current->flags |= PF_SYNCWRITE;
ret = filemap_fdatawrite(inode->i_mapping);
err = file->f_op->fsync(file, dentry, 0);
if (!ret)
@@ -326,6 +327,7 @@ asmlinkage long sys_fsync(unsigned int fd)
err = filemap_fdatawait(inode->i_mapping);
if (!ret)
ret = err;
+ current->flags &= ~PF_SYNCWRITE;
up(&inode->i_sem);
out_putf:
@@ -354,6 +356,7 @@ asmlinkage long sys_fdatasync(unsigned int fd)
goto out_putf;
down(&inode->i_sem);
+ current->flags |= PF_SYNCWRITE;
ret = filemap_fdatawrite(inode->i_mapping);
err = file->f_op->fsync(file, dentry, 1);
if (!ret)
@@ -361,6 +364,7 @@ asmlinkage long sys_fdatasync(unsigned int fd)
err = filemap_fdatawait(inode->i_mapping);
if (!ret)
ret = err;
+ current->flags &= ~PF_SYNCWRITE;
up(&inode->i_sem);
out_putf:
@@ -1447,6 +1451,17 @@ __getblk(struct block_device *bdev, sector_t block, int size)
}
EXPORT_SYMBOL(__getblk);
+/*
+ * Do async read-ahead on a buffer..
+ */
+void __breadahead(struct block_device *bdev, sector_t block, int size)
+{
+ struct buffer_head *bh = __getblk(bdev, block, size);
+ ll_rw_block(READA, 1, &bh);
+ brelse(bh);
+}
+EXPORT_SYMBOL(__breadahead);
+
/**
* __bread() - reads a specified block and returns the bh
* @block: number of block
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 03af9fb35147..a7aa89abfd5b 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
+Version 0.81
+------------
+Finish up CIFS packet digital signing for the default
+NTLM security case. This should help Windows 2003
+network interoperability since it is common for
+packet signing to be required now. Fix statfs (stat -f)
+which recently started returning errors due to
+invalid value (-1 instead of 0) being set in the
+struct kstatfs f_ffiles field.
+
Version 0.80
-----------
Fix oops on stopping oplock thread when removing cifs when
diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile
index 1295411affd2..94fd2b73c451 100644
--- a/fs/cifs/Makefile
+++ b/fs/cifs/Makefile
@@ -3,4 +3,4 @@
#
obj-$(CONFIG_CIFS) += cifs.o
-cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o
+cifs-objs := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o
diff --git a/fs/cifs/README b/fs/cifs/README
index 20626fb1aca4..12d93b7fadd1 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -1,5 +1,5 @@
-This is the CIFS VFS support for Linux. It supports many advanced network filesystem
-features such as heirarchical dfs like filesystem, hardlinks, locking and more.
+The CIFS VFS support for Linux supports many advanced network filesystem
+features such as heirarchical dfs like namespace, hardlinks, locking and more.
It was designed to comply with the SNIA CIFS Technical Reference (which supersedes
the 1992 X/Open SMB Standard) as well as to perform best practice practical
interoperability with Windows 2000, Windows XP, Samba and equivalent
@@ -9,43 +9,65 @@ For questions or bug reports please contact sfrench@samba.org (sfrench@us.ibm.co
Build instructions:
==================
-Get the kernel source e.g. http://linux.bkbits.net/linux-2.5 or http://www.kernel.org
-http://cifs.bkbits.net/linux-2.4
-make menuconfig (or make xconfig)
-select cifs from within the network filesystem choices
-save and exit
-make dep
-make modules (or "make" if you did not select CIFS VFS to be built as a module)
+For Linux 2.4:
+1a) Get the linux kernel source with cifs vfs already in it
+from bitkeeper via bk://cifs.bkbits.net/linux-2.4
+or
+1b) Get the kernel source (e.g.from http://www.kernel.org)
+and download the cifs vfs source (see the project page
+at http://us1.samba.org/samba/Linux_CIFS_client.html)
+and change directory into the top of the kernel directory
+then patch the kernel (e.g. "patch -p1 < cifs_24.patch")
+to add the cifs vfs to your kernel configure options if
+it has not already been added (e.g. current SuSE and UL
+users do not need to do not need that patch since the cifs vfs is
+already in the kernel configure menu) and then
+mkdir linux/fs/cifs and then copy the current cifs vfs files from
+the cifs download to your kernel build directory e.g.
+ cp <cifs_download_dir>/fs/cifs/* to <kernel_download_dir>/fs/cifs
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make dep
+6) make modules (or "make" if CIFS VFS not to be built as a module)
+
+For Linux 2.5:
+1) Download the kernel (e.g. from http://www.kernel.org or from bitkeeper
+at bk://linux.bkbits.net/linux-2.5) and change directory into the top
+of the kernel directory tree (e.g. /usr/src/linux-2.5.73)
+2) make menuconfig (or make xconfig)
+3) select cifs from within the network filesystem choices
+4) save and exit
+5) make
+
Installation instructions:
=========================
-If you have built the CIFS vfs as module (successfully)you
-simply type "make modules_install" (or if you prefer manually copy the file to
+If you have built the CIFS vfs as module (successfully) simply
+type "make modules_install" (or if you prefer, manually copy the file to
the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.o).
If you have built the CIFS vfs into the kernel itself, follow the instructions
for your distribution on how to install a new kernel (usually you
would simply type "make install").
-If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on the
-CIFS VFS web site) copy it to the directory /sbin (or the same directory in which
-mount.smbfs resides). Although no helper software is required, the installation
-of mount.cifs is recommended. Eventually the Samba 3.0 utility program "net"
+If you do not have the utility mount.cifs (in the Samba 3.0 source tree and on
+the CIFS VFS web site) copy it to the same directory in which mount.smbfs and
+similar files reside (usually /sbin). Although the helper software is required,
+mount.cifs is recommended. Eventually the Samba 3.0 utility program "net"
may also be helpful since it may someday provide easier mount syntax for users used
to Windows e.g.
net use <mount point> <UNC name or cifs URL>
-and there will likely be other helper programs available ala smbmount to provide
-additional optional function in the future. Note that running Winbind on all
-of your Linux clients is useful in mapping Uids and Gids consistently to the
-proper network user.
+Note that running Winbind on all of your Linux clients is useful in
+in mapping Uids and Gids consistently to the proper network user.
Samba Considerations
====================
To get the maximum benefit from the CIFS VFS, we recommend using a server that
-supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or Samba 3.0)
-but the CIFS vfs works fine with a wide variety of CIFS servers. Note that the
-uid, gid and file permissions will display default values if you do not have
-a server that supports the Unix extensions for CIFS (such as Samba 2.2.3 or
+supports the SNIA CIFS Unix Extensions standard (e.g. Samba 2.2.5 or later or
+Samba 3.0) but the CIFS vfs works fine with a wide variety of CIFS servers.
+Note that uid, gid and file permissions will display default values if you do
+not have a server that supports the Unix extensions for CIFS (such as Samba 2.2.3 or
later). To enable the Unix CIFS Extensions in the Samba server, add the line:
unix extensions = yes
to your smb.conf file on the server. Note that the following smb.conf settings are
@@ -81,15 +103,79 @@ either "pure-TCP" (port 445 TCP/IP CIFS connections) or RFC 1001/1002 support fo
"Netbios-Over-TCP/IP." Neither of these is likely to be a problem as most servers
support this. IPv6 support is planned for the future.
+CIFS VFS Mount Options
+======================
+A partial list of the supported mount options follows:
+ user The user name to use when trying to establish
+ the CIFS session.
+ password The user password. If the mount helper is
+ installed, the user will be prompted for password
+ if it is not supplied.
+ ip The ip address of the target server
+ unc The target server Universal Network Name (export) to
+ mount.
+ domain Set the SMB/CIFS workgroup name prepended to the
+ username during CIFS session establishment
+ uid If CIFS Unix extensions are not supported by the server
+ this overrides the default uid for inodes.
+ gid If CIFS Unix extensions are not supported by the server
+ this overrides the default gid for inodes.
+ file_mode If CIFS Unix extensions are not supported by the server
+ this overrides the default mode for file inodes.
+ dir_mode If CIFS Unix extensions are not supported by the server
+ this overrides the default mode for directory inodes.
+ port attempt to contact the server on this tcp port, before
+ trying the usual ports (port 445, then 139).
+ rsize default read size
+ wsize default write size
+ rw mount the network share read-write (note that the
+ server may still consider the share read-only)
+ ro mount network share read-only
+ version used to distinguish different versions of the
+ mount helper utility (not typically needed)
+
Misc /proc/fs/cifs Flags and Debug Info
=======================================
-Various experimental features and tracing can be enabled by changing flags in /proc/fs/cifs (after
-the cifs module has been installed or built into the kernel, e.g. insmod cifs). To enable
-a feature you can set it to 1 e.g. to enable tracing to the kernel message log you can do
-"echo 1 > /proc/fs/cifs/cifsFYI" and "echo 1 > /proc/fs/cifs/traceSMB"
-Also note that "cat /proc/fs/cifs/DebugData" will display some information about the currently
-active sessions and the shares that are mounted. Currently the ntlmv2 enablement and packet
-signing will not work since they the implementation is not quite complete, so do not enable
+Informational pseudo-files:
+ DebugData Displays information about active CIFS sessions
+ SimultaneousOps Counter which holds maximum number of
+ simultaneous outstanding SMB/CIFS requests.
+ Stats Lists summary resource usage information
+
+Configuration pseudo-files:
+ MultiuserMount If set to one, more than one CIFS session to
+ the same server ip address can be established
+ if more than one uid accesses the same mount
+ point and if the uids user/password mapping
+ information is available. (default is 0)
+ PacketSigningEnabled If set to one, cifs packet signing is enabled
+ (default 0)
+ cifsFYI If set to one, additional debug information is
+ logged to the system error log. (default 0)
+ ExtendedSecurity If set to one, SPNEGO session establishment
+ is allowed which enables more advanced
+ secure CIFS session establishment (default 0)
+ NTLMV2Enabled If set to one, more secure password hashes
+ are used when the server supports them and
+ when kerberos is not negotiated (default 0)
+ traceSMB If set to one, debug information is logged to the
+ system error log with the start of smb requests
+ and responses (default 0)
+ LookupCacheEnable If set to one, inode information is kept cached
+ for one second improving performance of lookups
+ (default 1)
+ OplockEnabled If set to one, safe distributed caching enabled.
+
+These experimental features and tracing can be enabled by changing flags in /proc/fs/cifs
+(after the cifs module has been installed or built into the kernel, e.g. insmod cifs).
+To enable a feature set it to 1 e.g. to enable tracing to the kernel message log
+type:
+ echo 1 > /proc/fs/cifs/cifsFYI
+and for more extensive tracing including the start of smb requests and responses
+ echo 1 > /proc/fs/cifs/traceSMB
+Also note that "cat /proc/fs/cifs/DebugData" will display some information about the
+active sessions and the shares that are mounted. NTLMv2 enablement and packet
+signing will not work since they the implementation is not quite complete. Do not enable
these flags unless you are doing specific testing. Enabling extended security works to
Windows 2000 Workstations and XP but not to Windows 2000 server or Samba since it does not
usually send "raw NTLMSSP" (instead it sends NTLMSSP encapsulated in SPNEGO/GSSAPI, which
diff --git a/fs/cifs/TODO b/fs/cifs/TODO
index e47e28db4f28..28a2c85fb926 100644
--- a/fs/cifs/TODO
+++ b/fs/cifs/TODO
@@ -1,4 +1,4 @@
-version 0.6.5 February 15, 2003
+version 0.8.1 July 4th, 2003
A Partial List of Known Problems and Missing Features
=====================================================
@@ -19,10 +19,9 @@ d) Kerberos/SPNEGO session setup support - (started)
e) NTLMv2 authentication and MD5-HMAC signing SMB PDUs - (mostly implemented)
signing necessary for some Windows 2003 servers in domain
- controller mode.
+ mode.
-f) oplock support (ie safe CIFS distributed file caching) is not quite complete.
-In addition Directory entry caching relies on a 1 second timer, rather than
+f) Directory entry caching relies on a 1 second timer, rather than
using FindNotify or equivalent. - (started)
g) There may be a few additional changes that could be done to take advantage
@@ -47,15 +46,16 @@ m) finish support for IPv6
n) send oplock break response when sent (oplock currently disabled in
/proc/fs/cifs)
-o) remove calls to set end of file by name when we already have file open
-(use the existing handle since some servers only support that and it
-reduces the oplock breaks coming from windows). Piggyback identical
+o) reduces the oplock breaks coming from windows). Piggyback identical
file opens on top of each other by incrementing reference count rather
than resending (helps reduce server resource utilization and avoid
spurious oplock breaks).
+p) Improve performance of readpages by sending more than one read
+at a time when 8 pages or more are requested.
-KNOWN BUGS (updated May 16, 2003)
+
+KNOWN BUGS (updated July 4th, 2003)
====================================
1) existing symbolic links (Windows reparse points) are recognized but
can not be created remotely. They are implemented for Samba and those that
@@ -74,8 +74,8 @@ Misc testing to do
1) check out max path names and max path name components against various server
types.
-2) Run dbench
+2) Run dbench. Modify file portion of ltp so it can run against a mounted network
+share and run it against cifs vfs.
-3) Finish high stress fsx testing on SMP clients
+3) Additional performance testing and optimization using iozone and similar tools.
-4) Additional performance testing and optimization
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 78425d07e5bc..e8a97a8949e6 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -34,7 +34,7 @@
void
toUpper(const struct nls_table *n, char *mixed_string)
{
- int i;
+ unsigned int i;
char temp;
for (i = 0; i < strlen(mixed_string); i++) {
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
new file mode 100755
index 000000000000..db3226e62720
--- /dev/null
+++ b/fs/cifs/cifsencrypt.c
@@ -0,0 +1,140 @@
+/*
+ * fs/cifs/cifsencrypt.c
+ *
+ * Copyright (c) International Business Machines Corp., 2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+#include "cifspdu.h"
+#include "cifsglob.h"
+#include "cifs_debug.h"
+#include "md5.h"
+
+/* Calculate and return the CIFS signature based on the mac key and the smb pdu */
+/* the 16 byte signature must be allocated by the caller */
+/* Note we only use the 1st eight bytes */
+/* Note that the smb header signature field on input contains the
+ sequence number before this function is called */
+
+extern void mdfour(unsigned char *out, unsigned char *in, int n);
+extern void E_md4hash(const unsigned char *passwd, unsigned char *p16);
+
+static int cifs_calculate_signature(const struct smb_hdr * cifs_pdu, const char * key, char * signature)
+{
+ struct MD5Context context;
+
+ if((cifs_pdu == NULL) || (signature == NULL))
+ return -EINVAL;
+
+ MD5Init(&context);
+ MD5Update(&context,key,CIFS_SESSION_KEY_SIZE+16);
+ MD5Update(&context,cifs_pdu->Protocol,cifs_pdu->smb_buf_length);
+ MD5Final(signature,&context);
+ return 0;
+}
+
+int cifs_sign_smb(struct smb_hdr * cifs_pdu, struct cifsSesInfo * ses,
+ __u32 * pexpected_response_sequence_number)
+{
+ int rc = 0;
+ char smb_signature[20];
+
+ /* BB remember to initialize sequence number elsewhere and initialize mac_signing key elsewhere BB */
+ /* BB remember to add code to save expected sequence number in midQ entry BB */
+
+ if((cifs_pdu == NULL) || (ses == NULL))
+ return -EINVAL;
+
+ if((le32_to_cpu(cifs_pdu->Flags2) & SMBFLG2_SECURITY_SIGNATURE) == 0)
+ return rc;
+
+ write_lock(&GlobalMid_Lock);
+ cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(ses->sequence_number);
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ *pexpected_response_sequence_number = ses->sequence_number++;
+ ses->sequence_number++;
+ write_unlock(&GlobalMid_Lock);
+
+ rc = cifs_calculate_signature(cifs_pdu, ses->mac_signing_key,smb_signature);
+ if(rc)
+ memset(cifs_pdu->Signature.SecuritySignature, 0, 8);
+ else
+ memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8);
+
+ return rc;
+}
+
+int cifs_verify_signature(struct smb_hdr * cifs_pdu, const char * mac_key,
+ __u32 expected_sequence_number)
+{
+ unsigned int rc;
+ char server_response_sig[8];
+ char what_we_think_sig_should_be[20];
+
+ if((cifs_pdu == NULL) || (mac_key == NULL))
+ return -EINVAL;
+
+ if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
+ return 0;
+
+ /* BB what if signatures are supposed to be on for session but server does not
+ send one? BB */
+ /* BB also do not verify oplock breaks for signature */
+
+ /* Do not need to verify session setups with signature "BSRSPYL " */
+ if(memcmp(cifs_pdu->Signature.SecuritySignature,"BSRSPYL ",8)==0)
+ cFYI(1,("dummy signature received for smb command 0x%x",cifs_pdu->Command));
+
+ expected_sequence_number = cpu_to_le32(expected_sequence_number);
+
+ /* save off the origiginal signature so we can modify the smb and check
+ its signature against what the server sent */
+ memcpy(server_response_sig,cifs_pdu->Signature.SecuritySignature,8);
+
+ cifs_pdu->Signature.Sequence.SequenceNumber = expected_sequence_number;
+ cifs_pdu->Signature.Sequence.Reserved = 0;
+
+ rc = cifs_calculate_signature(cifs_pdu, mac_key,
+ what_we_think_sig_should_be);
+
+ if(rc)
+ return rc;
+
+
+/* cifs_dump_mem("what we think it should be: ",what_we_think_sig_should_be,16); */
+
+ if(memcmp(server_response_sig, what_we_think_sig_should_be, 8))
+ return -EACCES;
+ else
+ return 0;
+
+}
+
+/* We fill in key by putting in 40 byte array which was allocated by caller */
+int cifs_calculate_mac_key(char * key, const char * rn, const char * password)
+{
+ char temp_key[16];
+ if ((key == NULL) || (rn == NULL) || (password == NULL))
+ return -EINVAL;
+
+ E_md4hash(password, temp_key); /* BB may have to do another md4 of it */
+ mdfour(key,temp_key,16);
+ memcpy(key+16,rn, CIFS_SESSION_KEY_SIZE);
+ return 0;
+}
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 1b3c43949f33..60e4629b1d67 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -165,7 +165,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
able to support more than this, but best to be safe
since Win2k and others can not handle very long filenames */
buf->f_files = 0; /* undefined */
- buf->f_ffree = -1; /* unlimited */
+ buf->f_ffree = 0; /* unlimited */
rc = CIFSSMBQFSInfo(xid, pTcon, buf, cifs_sb->local_nls);
@@ -178,7 +178,7 @@ cifs_statfs(struct super_block *sb, struct kstatfs *buf)
return 0; /* always return success? what if volume is no longer available? */
}
-static int cifs_permission(struct inode * inode, int mask)
+static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
/* the server does permission checks, we do not need to do it here */
return 0;
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 2776f7c0b7c2..0c0d756c53ae 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -46,8 +46,8 @@ extern void cifs_delete_inode(struct inode *);
/* Functions related to inodes */
extern struct inode_operations cifs_dir_inode_ops;
-extern int cifs_create(struct inode *, struct dentry *, int);
-extern struct dentry *cifs_lookup(struct inode *, struct dentry *);
+extern int cifs_create(struct inode *, struct dentry *, int, struct nameidata *);
+extern struct dentry *cifs_lookup(struct inode *, struct dentry *, struct nameidata *);
extern int cifs_unlink(struct inode *, struct dentry *);
extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
extern int cifs_mkdir(struct inode *, struct dentry *, int);
@@ -88,5 +88,9 @@ extern int cifs_follow_link(struct dentry *direntry, struct nameidata *nd);
extern int cifs_readlink(struct dentry *direntry, char *buffer, int buflen);
extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
const char *symname);
-
+extern int cifs_removexattr(struct dentry *, const char *);
+extern int cifs_setxattr(struct dentry *, const char *, const void *,
+ size_t, int);
+extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
+extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
#endif /* _CIFSSMB_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index ae3e49d1de45..5b0ae3bc20cb 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -149,7 +149,9 @@ struct cifsSesInfo {
struct TCP_Server_Info *server; /* pointer to server info */
atomic_t inUse; /* # of CURRENT users of this ses */
enum statusEnum status;
+ __u32 sequence_number; /* needed for CIFS PDU signature */
__u16 ipc_tid; /* special tid for connection to IPC share */
+ char mac_signing_key[CIFS_SESSION_KEY_SIZE + 16];
char *serverOS; /* name of operating system underlying the server */
char *serverNOS; /* name of network operating system that the server is running */
char *serverDomain; /* security realm of server */
@@ -249,6 +251,7 @@ struct mid_q_entry {
struct list_head qhead; /* mids waiting on reply from this server */
__u16 mid; /* multiplex id */
__u16 pid; /* process id */
+ __u32 sequence_number; /* for CIFS signing */
__u16 command; /* smb command code */
struct timeval when_sent; /* time when smb sent */
struct cifsSesInfo *ses; /* smb was sent to this server */
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h
index 1e6be8054126..bd9e6183deb2 100644
--- a/fs/cifs/cifspdu.h
+++ b/fs/cifs/cifspdu.h
@@ -307,7 +307,13 @@ struct smb_hdr {
__u8 Flags;
__u16 Flags2; /* note: le */
__u16 PidHigh; /* note: le */
- __u8 SecuritySignature[8]; /* note le */
+ union {
+ struct {
+ __u32 SequenceNumber; /* le */
+ __u32 Reserved; /* zero */
+ } Sequence;
+ __u8 SecuritySignature[8]; /* le */
+ } Signature;
__u8 pad[2];
__u16 Tid;
__u16 Pid; /* note: le */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index e557442f61fd..5b9dded835ec 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -79,8 +79,7 @@ extern int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo,
struct nls_table * nls_info);
extern int CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses);
extern int CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char *session_key, char *ntlm_session_key,
- const struct nls_table *);
+ char *ntlm_session_key, const struct nls_table *);
extern int CIFSSpnegoSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char *SecurityBlob,int SecurityBlobLength,
const struct nls_table *);
@@ -226,6 +225,11 @@ extern void tconInfoFree(struct cifsTconInfo *);
extern int cifs_demultiplex_thread(struct TCP_Server_Info *);
extern int cifs_reconnect(struct TCP_Server_Info *server);
+extern int cifs_sign_smb(struct smb_hdr *, struct cifsSesInfo *,__u32 *);
+extern int cifs_verify_signature(const struct smb_hdr *, const char * mac_key,
+ __u32 expected_sequence_number);
+extern int cifs_calculate_mac_key(char * key,const char * rn,const char * pass);
+
/* BB routines below not implemented yet BB */
extern int CIFSBuildServerList(int xid, char *serverBufferList,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 1d2d347e3adb..5761b8349297 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -106,9 +106,6 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
if (extended_security)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
- if (sign_CIFS_PDUs) {
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
- }
pSMB->ByteCount = strlen(protocols[0].name) + 1;
strncpy(pSMB->DialectsArray, protocols[0].name, 30);
@@ -260,10 +257,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses)
up(&ses->sesSem);
return -EBUSY;
}
- if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
rc = smb_init(SMB_COM_LOGOFF_ANDX, 2, 0 /* no tcon anymore */,
(void **) &pSMB, (void **) &smb_buffer_response);
+
+ if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
+
if (rc) {
up(&ses->sesSem);
return rc;
@@ -1657,8 +1657,6 @@ CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
if (ses->capabilities & CAP_DFS) {
pSMB->hdr.Flags2 |= SMBFLG2_DFS;
}
- if(ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- pSMB->hdr.Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index add558cc01af..f861fd7c5e4c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -200,7 +200,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
continue;
}
pdu_length = 4 + ntohl(smb_buffer->smb_buf_length);
- cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length)); /* BB */
+ cFYI(1, ("Peek length rcvd: %d with smb length: %d", length, pdu_length));
temp = (char *) smb_buffer;
if (length > 3) {
@@ -332,8 +332,9 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
kfree(server);
} else /* BB need to more gracefully handle the rare negative session
response case because response will be still outstanding */
- cERROR(1, ("There are still active MIDs in queue and we are exiting but we can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!")); /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
-/* BB Need to fix bug in error path above - perhaps wait until smb requests
+ cERROR(1, ("Active MIDs in queue while exiting - can not delete mid_q_entries or TCP_Server_Info structure due to pending requests MEMORY LEAK!!"));
+ /* BB wake up waitors, and/or wait and/or free stale mids and try again? BB */
+ /* BB Need to fix bug in error path above - perhaps wait until smb requests
time out and then free the tcp per server struct BB */
read_unlock(&GlobalSMBSeslock);
@@ -641,6 +642,7 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */
rc = CIFSSMBNegotiate(xid, pSesInfo);
pSesInfo->capabilities = pSesInfo->server->capabilities;
+ pSesInfo->sequence_number = 0;
if (!rc) {
cFYI(1,("Security Mode: 0x%x Capabilities: 0x%x Time Zone: %d",
pSesInfo->server->secMode,
@@ -671,6 +673,8 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,ntlm_session_key);
+ /* BB add call to save MAC key here BB */
+
/* for better security the weaker lanman hash not sent
in AuthSessSetup so why bother calculating it */
/* toUpper(nls_info,
@@ -689,10 +693,10 @@ int setup_session(unsigned int xid, struct cifsSesInfo *pSesInfo, struct nls_tab
SMBNTencrypt(pSesInfo->password_with_pad,
pSesInfo->server->cryptKey,
ntlm_session_key);
+
+ cifs_calculate_mac_key(pSesInfo->mac_signing_key, ntlm_session_key, pSesInfo->password_with_pad);
rc = CIFSSessSetup(xid, pSesInfo,
- session_key,
- ntlm_session_key,
- nls_info);
+ ntlm_session_key, nls_info);
}
if (rc) {
cERROR(1,("Send error in SessSetup = %d",rc));
@@ -1024,7 +1028,6 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
int
CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
char session_key[CIFS_SESSION_KEY_SIZE],
- char session_key2[CIFS_SESSION_KEY_SIZE],
const struct nls_table *nls_codepage)
{
struct smb_hdr *smb_buffer;
@@ -1081,9 +1084,9 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
pSMB->req_no_secext.CaseSensitivePasswordLength =
cpu_to_le16(CIFS_SESSION_KEY_SIZE);
bcc_ptr = pByteArea(smb_buffer);
- /* memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
+ /* memcpy(bcc_ptr, (char *) lm_session_key, CIFS_SESSION_KEY_SIZE);
bcc_ptr += CIFS_SESSION_KEY_SIZE; */
- memcpy(bcc_ptr, (char *) session_key2, CIFS_SESSION_KEY_SIZE);
+ memcpy(bcc_ptr, (char *) session_key, CIFS_SESSION_KEY_SIZE);
bcc_ptr += CIFS_SESSION_KEY_SIZE;
if (ses->capabilities & CAP_UNICODE) {
@@ -1094,7 +1097,7 @@ CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
if(user == NULL)
bytes_returned = 0; /* skill null user */
else
- bytes_returned =
+ bytes_returned =
cifs_strtoUCS((wchar_t *) bcc_ptr, user, 100, nls_codepage);
bcc_ptr += 2 * bytes_returned; /* convert num 16 bit words to bytes */
bcc_ptr += 2; /* trailing null */
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 123639718e99..69c4b70e6b46 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -119,7 +119,8 @@ build_wildcard_path_from_dentry(struct dentry *direntry)
/* Inode operations in similar order to how they appear in the Linux file fs.h */
int
-cifs_create(struct inode *inode, struct dentry *direntry, int mode)
+cifs_create(struct inode *inode, struct dentry *direntry, int mode,
+ struct nameidata *nd)
{
int rc = -ENOENT;
int xid;
@@ -178,7 +179,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode)
}
struct dentry *
-cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry)
+cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd)
{
int rc, xid;
struct cifs_sb_info *cifs_sb;
@@ -262,7 +263,7 @@ cifs_dir_open(struct inode *inode, struct file *file)
}
static int
-cifs_d_revalidate(struct dentry *direntry, int flags)
+cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
{
int isValid = 1;
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 19b4bd43dcab..3d78ae445e3c 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -635,9 +635,9 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
struct cifsFileInfo *open_file = NULL;
FILE_BASIC_INFO time_buf;
int set_time = FALSE;
- __u64 mode = 0xFFFFFFFFFFFFFFFF;
- __u64 uid = 0xFFFFFFFFFFFFFFFF;
- __u64 gid = 0xFFFFFFFFFFFFFFFF;
+ __u64 mode = 0xFFFFFFFFFFFFFFFFULL;
+ __u64 uid = 0xFFFFFFFFFFFFFFFFULL;
+ __u64 gid = 0xFFFFFFFFFFFFFFFFULL;
struct cifsInodeInfo *cifsInode;
xid = GetXid();
diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c
index 79cbdc7feef6..82e27cac1c53 100644
--- a/fs/cifs/smbdes.c
+++ b/fs/cifs/smbdes.c
@@ -399,7 +399,7 @@ SamOEMhash(unsigned char *data, unsigned char *key, int val)
s_box[ind] = s_box[j];
s_box[j] = tc;
}
- for (ind = 0; ind < (val ? 516 : 16); ind++) {
+ for (ind = 0; ind < val; ind++) {
unsigned char tc;
unsigned char t;
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c
index 2e84b92c010f..9c810c517cf0 100644
--- a/fs/cifs/smbencrypt.c
+++ b/fs/cifs/smbencrypt.c
@@ -5,7 +5,8 @@
Copyright (C) Andrew Tridgell 1992-2000
Copyright (C) Luke Kenneth Casson Leighton 1996-2000
Modified by Jeremy Allison 1995.
- Modified by Steve French (sfrench@us.ibm.com) 2002
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+ Modified by Steve French (sfrench@us.ibm.com) 2002-2003
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -97,13 +98,15 @@ SMBencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
E_P16(p14, p21);
SMBOWFencrypt(p21, c8, p24);
-
+
#ifdef DEBUG_PASSWORD
DEBUG(100, ("SMBencrypt: lm#, challenge, response\n"));
dump_data(100, (char *) p21, 16);
dump_data(100, (char *) c8, 8);
dump_data(100, (char *) p24, 24);
#endif
+ memset(p14,0,15);
+ memset(p21,0,21);
}
/* Routines for Windows NT MD4 Hash functions. */
@@ -161,6 +164,7 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16)
len = _my_wcslen(wpwd) * sizeof (__u16);
mdfour(p16, (unsigned char *) wpwd, len);
+ memset(wpwd,0,129 * 2);
}
/* Does both the NT and LM owfs of a user's password */
@@ -222,7 +226,7 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n,
/* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */
- /* do not think it is supposed to be uppercased */
+ /* BB user and domain may need to be uppercased */
user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage);
domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage);
@@ -297,8 +301,52 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24)
#endif
}
-int
-make_oem_passwd_hash(char data[516], const char *passwd,
+/* Does the md5 encryption from the NT hash for NTLMv2. */
+void
+SMBOWFencrypt_ntv2(const unsigned char kr[16],
+ const struct data_blob * srv_chal,
+ const struct data_blob * cli_chal, unsigned char resp_buf[16])
+{
+ struct HMACMD5Context ctx;
+
+ hmac_md5_init_limK_to_64(kr, 16, &ctx);
+ hmac_md5_update(srv_chal->data, srv_chal->length, &ctx);
+ hmac_md5_update(cli_chal->data, cli_chal->length, &ctx);
+ hmac_md5_final(resp_buf, &ctx);
+
+#ifdef DEBUG_PASSWORD
+ DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
+ dump_data(100, srv_chal->data, srv_chal->length);
+ dump_data(100, cli_chal->data, cli_chal->length);
+ dump_data(100, resp_buf, 16);
+#endif
+}
+
+static struct data_blob LMv2_generate_response(const unsigned char ntlm_v2_hash[16],
+ const struct data_blob * server_chal)
+{
+ unsigned char lmv2_response[16];
+ struct data_blob lmv2_client_data/* = data_blob(NULL, 8)*/; /* BB Fix BB */
+ struct data_blob final_response /* = data_blob(NULL, 24)*/; /* BB Fix BB */
+
+ /* LMv2 */
+ /* client-supplied random data */
+ get_random_bytes(lmv2_client_data.data, lmv2_client_data.length);
+ /* Given that data, and the challenge from the server, generate a response */
+ SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
+ memcpy(final_response.data, lmv2_response, sizeof(lmv2_response));
+
+ /* after the first 16 bytes is the random data we generated above,
+ so the server can verify us with it */
+ memcpy(final_response.data+sizeof(lmv2_response),
+ lmv2_client_data.data, lmv2_client_data.length);
+
+/* data_blob_free(&lmv2_client_data); */ /* BB fix BB */
+
+ return final_response;
+}
+
+int make_oem_passwd_hash(char data[516], const char *passwd,
unsigned char old_pw_hash[16], int unicode)
{
int new_pw_len = strlen(passwd) * (unicode ? 2 : 1);
@@ -333,32 +381,11 @@ make_oem_passwd_hash(char data[516], const char *passwd,
DEBUG(100, ("make_oem_passwd_hash\n"));
dump_data(100, data, 516);
#endif
- SamOEMhash((unsigned char *) data, (unsigned char *) old_pw_hash, TRUE);
+ SamOEMhash((unsigned char *) data, (unsigned char *) old_pw_hash, 516);
return TRUE;
}
-/* Does the md5 encryption from the NT hash for NTLMv2. */
-void
-SMBOWFencrypt_ntv2(const unsigned char kr[16],
- const struct data_blob srv_chal,
- const struct data_blob cli_chal, unsigned char resp_buf[16])
-{
- struct HMACMD5Context ctx;
-
- hmac_md5_init_limK_to_64(kr, 16, &ctx);
- hmac_md5_update(srv_chal.data, srv_chal.length, &ctx);
- hmac_md5_update(cli_chal.data, cli_chal.length, &ctx);
- hmac_md5_final(resp_buf, &ctx);
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n"));
- dump_data(100, srv_chal.data, srv_chal.length);
- dump_data(100, cli_chal.data, cli_chal.length);
- dump_data(100, resp_buf, 16);
-#endif
-}
-
void
SMBsesskeygen_ntv2(const unsigned char kr[16],
const unsigned char *nt_resp, __u8 sess_key[16])
@@ -407,6 +434,44 @@ encode_pw_buffer(char buffer[516], char *new_pw, int new_pw_length)
return TRUE;
}
+int SMBNTLMv2encrypt(const char *user, const char *domain, const char *password,
+ const struct data_blob *server_chal,
+ const struct data_blob *names_blob,
+ struct data_blob *lm_response, struct data_blob *nt_response,
+ struct data_blob *nt_session_key,struct nls_table * nls_codepage)
+{
+ unsigned char nt_hash[16];
+ unsigned char ntlm_v2_hash[16];
+ E_md4hash(password, nt_hash);
+
+ /* We don't use the NT# directly. Instead we use it mashed up with
+ the username and domain.
+ This prevents username swapping during the auth exchange
+ */
+ ntv2_owf_gen(nt_hash, user, domain, ntlm_v2_hash,nls_codepage);
+
+ if (nt_response) {
+/* *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal,
+ names_blob); */ /* BB fix BB */
+ if (nt_session_key) {
+/* *nt_session_key = data_blob(NULL, 16); */ /* BB fix BB */
+
+ /* The NTLMv2 calculations also provide a session key, for signing etc later */
+ /* use only the first 16 bytes of nt_response for session key */
+ SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, nt_session_key->data);
+ }
+ }
+
+ /* LMv2 */
+
+ if (lm_response) {
+ *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal);
+ }
+
+ return TRUE;
+}
+
+
/***********************************************************
SMB signing - setup the MAC key.
************************************************************/
@@ -455,7 +520,7 @@ cli_caclulate_sign_mac(struct smb_hdr *outbuf, __u8 * mac_key,
be32_to_cpu(outbuf->smb_buf_length));
MD5Final(calc_md5_mac, &md5_ctx);
- memcpy(outbuf->SecuritySignature, calc_md5_mac, 8);
+ memcpy(outbuf->Signature.SecuritySignature, calc_md5_mac, 8);
(*send_seq_num)++;
*reply_seq_num = *send_seq_num;
(*send_seq_num)++;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 4705a16d9ef5..5d976743f720 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -154,12 +154,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer,
/* smb header is converted in header_assemble. bcc and rest of SMB word
area, and byte area if necessary, is converted to littleendian in
- cifssmb.c and RFC1001 len is converted to bigendian in smb_send */
- if (smb_buf_length > 12)
- smb_buffer->Flags2 = cpu_to_le16(smb_buffer->Flags2);
-
- /* if(smb_buffer->Flags2 & SMBFLG2_SECURITY_SIGNATURE)
- sign_smb(smb_buffer); */ /* BB enable when signing tested more */
+ cifssmb.c and RFC1001 len is converted to bigendian in smb_send
+ Flags2 is converted in SendReceive */
smb_buffer->smb_buf_length = cpu_to_be32(smb_buffer->smb_buf_length);
cFYI(1, ("Sending smb of length %d ", smb_buf_length));
@@ -200,6 +196,12 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
DeleteMidQEntry(midQ);
return -EIO;
}
+
+ if (in_buf->smb_buf_length > 12)
+ in_buf->Flags2 = cpu_to_le16(in_buf->Flags2);
+
+ rc = cifs_sign_smb(in_buf, ses, &midQ->sequence_number);
+
midQ->midState = MID_REQUEST_SUBMITTED;
rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length,
(struct sockaddr *) &(ses->server->sockAddr));
@@ -247,11 +249,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
memcpy(out_buf, midQ->resp_buf,
receive_len +
4 /* include 4 byte RFC1001 header */ );
- /* convert the length back to a form that we can use */
dump_smb(out_buf, 92);
+ /* convert the length into a more usable form */
out_buf->smb_buf_length =
be32_to_cpu(out_buf->smb_buf_length);
+ if((out_buf->smb_buf_length > 24) &&
+ (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))) {
+ rc = cifs_verify_signature(out_buf, ses->mac_signing_key,midQ->sequence_number); /* BB fix BB */
+ if(rc)
+ cFYI(1,("Unexpected signature received from server"));
+ }
+
if (out_buf->smb_buf_length > 12)
out_buf->Flags2 = le16_to_cpu(out_buf->Flags2);
if (out_buf->smb_buf_length > 28)
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
new file mode 100644
index 000000000000..e377fa0247f0
--- /dev/null
+++ b/fs/cifs/xattr.c
@@ -0,0 +1,56 @@
+/*
+ * fs/cifs/xattr.c
+ *
+ * Copyright (c) International Business Machines Corp., 2003
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/fs.h>
+
+int cifs_removexattr(struct dentry * direntry, const char * name)
+{
+ int rc = -EOPNOTSUPP;
+ return rc;
+}
+
+int cifs_setxattr(struct dentry * direntry, const char * name,
+ const void * value, size_t size, int flags)
+{
+ int rc = -EOPNOTSUPP;
+ return rc;
+}
+
+ssize_t cifs_getxattr(struct dentry * direntry, const char * name,
+ void * value, size_t size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+ return rc;
+}
+
+ssize_t cifs_listxattr(struct dentry * direntry, char * ea_data, size_t ea_size)
+{
+ ssize_t rc = -EOPNOTSUPP;
+
+ /* return dosattributes as pseudo xattr */
+ /* return alt name if available as pseudo attr */
+
+ /* if proc/fs/cifs/streamstoxattr is set then
+ search server for EAs or streams to
+ returns as xattrs */
+
+ return rc;
+}
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index a7952879bd8f..2917ab9f4976 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -28,9 +28,9 @@
#include <linux/coda_proc.h>
/* dir inode-ops */
-static int coda_create(struct inode *dir, struct dentry *new, int mode);
+static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);
static int coda_mknod(struct inode *dir, struct dentry *new, int mode, dev_t rdev);
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *target);
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
static int coda_link(struct dentry *old_dentry, struct inode *dir_inode,
struct dentry *entry);
static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
@@ -45,7 +45,7 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);
/* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de, int);
+static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
static int coda_dentry_delete(struct dentry *);
/* support routines */
@@ -90,7 +90,7 @@ struct file_operations coda_dir_operations = {
/* inode operations for directories */
/* access routines: lookup, readlink, permission */
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry)
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
{
struct inode *res_inode = NULL;
struct ViceFid resfid = {0,0,0};
@@ -147,7 +147,7 @@ exit:
}
-int coda_permission(struct inode *inode, int mask)
+int coda_permission(struct inode *inode, int mask, struct nameidata *nd)
{
int error = 0;
@@ -190,7 +190,7 @@ static inline void coda_dir_changed(struct inode *dir, int link)
}
/* creation routines: create, mknod, mkdir, link, symlink */
-static int coda_create(struct inode *dir, struct dentry *de, int mode)
+static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
{
int error=0;
const char *name=de->d_name.name;
@@ -627,7 +627,7 @@ static int coda_venus_readdir(struct file *filp, filldir_t filldir,
}
/* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de, int flags)
+static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
{
struct inode *inode = de->d_inode;
struct coda_inode_info *cii;
diff --git a/fs/coda/file.c b/fs/coda/file.c
index 486ca3af939c..8d4865cbc91a 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -153,19 +153,22 @@ int coda_flush(struct file *coda_file)
struct inode *coda_inode;
int err = 0, fcnt;
+ lock_kernel();
+
coda_vfs_stat.flush++;
/* last close semantics */
fcnt = file_count(coda_file);
- if (fcnt > 1) return 0;
+ if (fcnt > 1)
+ goto out;
/* No need to make an upcall when we have not made any modifications
* to the file */
if ((coda_file->f_flags & O_ACCMODE) == O_RDONLY)
- return 0;
+ goto out;
if (use_coda_close)
- return 0;
+ goto out;
cfi = CODA_FTOC(coda_file);
BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -180,6 +183,8 @@ int coda_flush(struct file *coda_file)
err = 0;
}
+out:
+ unlock_kernel();
return err;
}
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index 67228f3c2122..e10ac76438c0 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -24,7 +24,8 @@
#include <linux/coda_psdev.h>
/* pioctl ops */
-static int coda_ioctl_permission(struct inode *inode, int mask);
+static int coda_ioctl_permission(struct inode *inode, int mask,
+ struct nameidata *nd);
static int coda_pioctl(struct inode * inode, struct file * filp,
unsigned int cmd, unsigned long user_data);
@@ -41,7 +42,8 @@ struct file_operations coda_ioctl_operations = {
};
/* the coda pioctl inode ops */
-static int coda_ioctl_permission(struct inode *inode, int mask)
+static int coda_ioctl_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
{
return 0;
}
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index c6d6844796bb..b6a83ad7b325 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -342,7 +342,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/*
* Lookup and fill in the inode data..
*/
-static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
unsigned int offset = 0;
int sorted;
diff --git a/fs/devfs/base.c b/fs/devfs/base.c
index c632affe5dae..5c787aaa4901 100644
--- a/fs/devfs/base.c
+++ b/fs/devfs/base.c
@@ -2175,7 +2175,7 @@ static struct dentry_operations devfs_dops =
.d_iput = devfs_d_iput,
};
-static int devfs_d_revalidate_wait (struct dentry *dentry, int flags);
+static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *);
static struct dentry_operations devfs_wait_dops =
{
@@ -2212,7 +2212,7 @@ struct devfs_lookup_struct
/* XXX: this doesn't handle the case where we got a negative dentry
but a devfs entry has been registered in the meanwhile */
-static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
+static int devfs_d_revalidate_wait (struct dentry *dentry, struct nameidata *nd)
{
struct inode *dir = dentry->d_parent->d_inode;
struct fs_info *fs_info = dir->i_sb->s_fs_info;
@@ -2265,7 +2265,7 @@ static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
/* Inode operations for device entries follow */
-static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry)
+static struct dentry *devfs_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct devfs_entry tmp; /* Must stay in scope until devfsd idle again */
struct devfs_lookup_struct lookup_info;
diff --git a/fs/dquot.c b/fs/dquot.c
index 34f9417ed71a..9b3a6aae6c5f 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -74,6 +74,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/security.h>
+#include <linux/kmod.h>
#include <asm/uaccess.h>
@@ -96,6 +97,7 @@ spinlock_t dq_data_lock = SPIN_LOCK_UNLOCKED;
static char *quotatypes[] = INITQFNAMES;
static struct quota_format_type *quota_formats; /* List of registered formats */
+static struct quota_module_name module_names[] = INIT_QUOTA_MODULE_NAMES;
int register_quota_format(struct quota_format_type *fmt)
{
@@ -123,8 +125,19 @@ static struct quota_format_type *find_quota_format(int id)
spin_lock(&dq_list_lock);
for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next);
- if (actqf && !try_module_get(actqf->qf_owner))
- actqf = NULL;
+ if (!actqf || !try_module_get(actqf->qf_owner)) {
+ int qm;
+
+ for (qm = 0; module_names[qm].qm_fmt_id && module_names[qm].qm_fmt_id != id; qm++);
+ if (!module_names[qm].qm_fmt_id || request_module(module_names[qm].qm_mod_name)) {
+ actqf = NULL;
+ goto out;
+ }
+ for (actqf = quota_formats; actqf && actqf->qf_fmt_id != id; actqf = actqf->qf_next);
+ if (actqf && !try_module_get(actqf->qf_owner))
+ actqf = NULL;
+ }
+out:
spin_unlock(&dq_list_lock);
return actqf;
}
diff --git a/fs/efs/namei.c b/fs/efs/namei.c
index 086630cc435a..e6c7210f0a68 100644
--- a/fs/efs/namei.c
+++ b/fs/efs/namei.c
@@ -57,7 +57,7 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
return(0);
}
-struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry) {
+struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
efs_ino_t inodenum;
struct inode * inode = NULL;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index b17cdae0109c..d6fef13ef5e0 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -443,29 +443,17 @@ void eventpoll_init_file(struct file *file)
/*
- * This is called from inside fs/file_table.c:__fput() to unlink files
- * from the eventpoll interface. We need to have this facility to cleanup
- * correctly files that are closed without being removed from the eventpoll
- * interface.
+ * This is called from eventpoll_release() to unlink files from the eventpoll
+ * interface. We need to have this facility to cleanup correctly files that are
+ * closed without being removed from the eventpoll interface.
*/
-void eventpoll_release(struct file *file)
+void eventpoll_release_file(struct file *file)
{
struct list_head *lsthead = &file->f_ep_links;
struct eventpoll *ep;
struct epitem *epi;
/*
- * Fast check to avoid the get/release of the semaphore. Since
- * we're doing this outside the semaphore lock, it might return
- * false negatives, but we don't care. It'll help in 99.99% of cases
- * to avoid the semaphore lock. False positives simply cannot happen
- * because the file in on the way to be removed and nobody ( but
- * eventpoll ) has still a reference to this file.
- */
- if (list_empty(lsthead))
- return;
-
- /*
* We don't want to get "file->f_ep_lock" because it is not
* necessary. It is not necessary because we're in the "struct file"
* cleanup path, and this means that noone is using this file anymore.
@@ -541,7 +529,7 @@ eexit_1:
/*
* The following function implement the controller interface for the eventpoll
* file that enable the insertion/removal/change of file descriptors inside
- * the interest set. It rapresents the kernel part of the user spcae epoll_ctl(2).
+ * the interest set. It rapresents the kernel part of the user space epoll_ctl(2).
*/
asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
{
@@ -551,8 +539,8 @@ asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *even
struct epitem *epi;
struct epoll_event epds;
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u)\n",
- current, epfd, op, fd, event->events));
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
+ current, epfd, op, fd, event));
error = -EFAULT;
if (copy_from_user(&epds, event, sizeof(struct epoll_event)))
@@ -633,8 +621,8 @@ eexit_3:
eexit_2:
fput(file);
eexit_1:
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %u) = %d\n",
- current, epfd, op, fd, event->events, error));
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
+ current, epfd, op, fd, event, error));
return error;
}
diff --git a/fs/exec.c b/fs/exec.c
index 204d0a3a1565..36a11c0eddd1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -117,7 +117,8 @@ asmlinkage long sys_uselib(const char __user * library)
struct nameidata nd;
int error;
- error = user_path_walk(library, &nd);
+ nd.intent.open.flags = O_RDONLY;
+ error = __user_walk(library, LOOKUP_FOLLOW|LOOKUP_OPEN, &nd);
if (error)
goto out;
@@ -125,7 +126,7 @@ asmlinkage long sys_uselib(const char __user * library)
if (!S_ISREG(nd.dentry->d_inode->i_mode))
goto exit;
- error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC);
+ error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
if (error)
goto exit;
@@ -392,7 +393,7 @@ int setup_arg_pages(struct linux_binprm *bprm)
if (!mpnt)
return -ENOMEM;
- if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+ if (security_vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
kmem_cache_free(vm_area_cachep, mpnt);
return -ENOMEM;
}
@@ -441,9 +442,9 @@ static inline void free_arg_pages(struct linux_binprm *bprm)
{
int i;
- for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+ for (i = 0; i < MAX_ARG_PAGES; i++) {
if (bprm->page[i])
- __free_page(bprm->page[i]);
+ __free_page(bprm->page[i]);
bprm->page[i] = NULL;
}
}
@@ -461,7 +462,7 @@ struct file *open_exec(const char *name)
file = ERR_PTR(-EACCES);
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
S_ISREG(inode->i_mode)) {
- int err = permission(inode, MAY_EXEC);
+ int err = permission(inode, MAY_EXEC, &nd);
if (!err && !(inode->i_mode & 0111))
err = -EACCES;
file = ERR_PTR(err);
@@ -758,12 +759,6 @@ int flush_old_exec(struct linux_binprm * bprm)
char * name;
int i, ch, retval;
- /*
- * Release all of the old mmap stuff
- */
- retval = exec_mmap(bprm->mm);
- if (retval)
- goto out;
/*
* Make sure we have a private signal table and that
* we are unassociated from the previous thread group.
@@ -772,6 +767,15 @@ int flush_old_exec(struct linux_binprm * bprm)
if (retval)
goto out;
+ /*
+ * Release all of the old mmap stuff
+ */
+ retval = exec_mmap(bprm->mm);
+ if (retval)
+ goto out;
+
+ bprm->mm = NULL; /* We're using it now */
+
/* This is the point of no return */
current->sas_ss_sp = current->sas_ss_size = 0;
@@ -791,7 +795,7 @@ int flush_old_exec(struct linux_binprm * bprm)
flush_thread();
if (bprm->e_uid != current->euid || bprm->e_gid != current->egid ||
- permission(bprm->file->f_dentry->d_inode,MAY_READ))
+ permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL))
current->mm->dumpable = 0;
/* An exec changes our domain. We are no longer part of the thread
@@ -999,7 +1003,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
}
read_lock(&binfmt_lock);
put_binfmt(fmt);
- if (retval != -ENOEXEC)
+ if (retval != -ENOEXEC || bprm->mm == NULL)
break;
if (!bprm->file) {
read_unlock(&binfmt_lock);
@@ -1007,7 +1011,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
}
}
read_unlock(&binfmt_lock);
- if (retval != -ENOEXEC) {
+ if (retval != -ENOEXEC || bprm->mm == NULL) {
break;
#ifdef CONFIG_KMOD
}else{
@@ -1035,7 +1039,6 @@ int do_execve(char * filename,
struct linux_binprm bprm;
struct file *file;
int retval;
- int i;
sched_balance_exec();
@@ -1103,17 +1106,14 @@ int do_execve(char * filename,
out:
/* Something went wrong, return the inode and free the argument pages*/
- for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
- struct page * page = bprm.page[i];
- if (page)
- __free_page(page);
- }
+ free_arg_pages(&bprm);
if (bprm.security)
security_bprm_free(&bprm);
out_mm:
- mmdrop(bprm.mm);
+ if (bprm.mm)
+ mmdrop(bprm.mm);
out_file:
if (bprm.file) {
@@ -1256,10 +1256,21 @@ void format_corename(char *corename, const char *pattern, long signr)
static void zap_threads (struct mm_struct *mm)
{
struct task_struct *g, *p;
+ struct task_struct *tsk = current;
+ struct completion *vfork_done = tsk->vfork_done;
+
+ /*
+ * Make sure nobody is waiting for us to release the VM,
+ * otherwise we can deadlock when we wait on each other
+ */
+ if (vfork_done) {
+ tsk->vfork_done = NULL;
+ complete(vfork_done);
+ }
read_lock(&tasklist_lock);
do_each_thread(g,p)
- if (mm == p->mm && p != current) {
+ if (mm == p->mm && p != tsk) {
force_sig_specific(SIGKILL, p);
mm->core_waiters++;
}
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 9367f43f4acb..0df165f8ee01 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -1,7 +1,7 @@
/*
* linux/fs/ext2/acl.c
*
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
#include <linux/init.h>
@@ -19,7 +19,7 @@ static struct posix_acl *
ext2_acl_from_disk(const void *value, size_t size)
{
const char *end = (char *)value + size;
- int n, count;
+ size_t n, count;
struct posix_acl *acl;
if (!value)
@@ -85,7 +85,7 @@ ext2_acl_to_disk(const struct posix_acl *acl, size_t *size)
{
ext2_acl_header *ext_acl;
char *e;
- int n;
+ size_t n;
*size = ext2_acl_size(acl->a_count);
ext_acl = (ext2_acl_header *)kmalloc(sizeof(ext2_acl_header) +
@@ -124,16 +124,41 @@ fail:
return ERR_PTR(-EINVAL);
}
+static inline struct posix_acl *
+ext2_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+ struct posix_acl *acl = EXT2_ACL_NOT_CACHED;
+
+ spin_lock(&inode->i_lock);
+ if (*i_acl != EXT2_ACL_NOT_CACHED)
+ acl = posix_acl_dup(*i_acl);
+ spin_unlock(&inode->i_lock);
+
+ return acl;
+}
+
+static inline void
+ext2_iset_acl(struct inode *inode, struct posix_acl **i_acl,
+ struct posix_acl *acl)
+{
+ spin_lock(&inode->i_lock);
+ if (*i_acl != EXT2_ACL_NOT_CACHED)
+ posix_acl_release(*i_acl);
+ *i_acl = posix_acl_dup(acl);
+ spin_unlock(&inode->i_lock);
+}
+
/*
- * inode->i_sem: down
+ * inode->i_sem: don't care
*/
static struct posix_acl *
ext2_get_acl(struct inode *inode, int type)
{
+ const size_t max_size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+ struct ext2_inode_info *ei = EXT2_I(inode);
int name_index;
char *value;
- struct posix_acl *acl, **p_acl;
- const size_t size = ext2_acl_size(EXT2_ACL_MAX_ENTRIES);
+ struct posix_acl *acl;
int retval;
if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -141,36 +166,45 @@ ext2_get_acl(struct inode *inode, int type)
switch(type) {
case ACL_TYPE_ACCESS:
- p_acl = &EXT2_I(inode)->i_acl;
+ acl = ext2_iget_acl(inode, &ei->i_acl);
+ if (acl != EXT2_ACL_NOT_CACHED)
+ return acl;
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
- p_acl = &EXT2_I(inode)->i_default_acl;
+ acl = ext2_iget_acl(inode, &ei->i_default_acl);
+ if (acl != EXT2_ACL_NOT_CACHED)
+ return acl;
name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
return ERR_PTR(-EINVAL);
}
- if (*p_acl != EXT2_ACL_NOT_CACHED)
- return posix_acl_dup(*p_acl);
- value = kmalloc(size, GFP_KERNEL);
+ value = kmalloc(max_size, GFP_KERNEL);
if (!value)
return ERR_PTR(-ENOMEM);
- retval = ext2_xattr_get(inode, name_index, "", value, size);
-
- if (retval == -ENODATA || retval == -ENOSYS)
- *p_acl = acl = NULL;
- else if (retval < 0)
- acl = ERR_PTR(retval);
- else {
+ retval = ext2_xattr_get(inode, name_index, "", value, max_size);
+ acl = ERR_PTR(retval);
+ if (retval >= 0)
acl = ext2_acl_from_disk(value, retval);
- if (!IS_ERR(acl))
- *p_acl = posix_acl_dup(acl);
- }
+ else if (retval == -ENODATA || retval == -ENOSYS)
+ acl = NULL;
kfree(value);
+
+ if (!IS_ERR(acl)) {
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ ext2_iset_acl(inode, &ei->i_acl, acl);
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ ext2_iset_acl(inode, &ei->i_default_acl, acl);
+ break;
+ }
+ }
return acl;
}
@@ -180,9 +214,9 @@ ext2_get_acl(struct inode *inode, int type)
static int
ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
{
+ struct ext2_inode_info *ei = EXT2_I(inode);
int name_index;
void *value = NULL;
- struct posix_acl **p_acl;
size_t size;
int error;
@@ -194,7 +228,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
switch(type) {
case ACL_TYPE_ACCESS:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_ACCESS;
- p_acl = &EXT2_I(inode)->i_acl;
if (acl) {
mode_t mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
@@ -211,7 +244,6 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
case ACL_TYPE_DEFAULT:
name_index = EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT;
- p_acl = &EXT2_I(inode)->i_default_acl;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
break;
@@ -232,15 +264,26 @@ ext2_set_acl(struct inode *inode, int type, struct posix_acl *acl)
if (value)
kfree(value);
if (!error) {
- if (*p_acl && *p_acl != EXT2_ACL_NOT_CACHED)
- posix_acl_release(*p_acl);
- *p_acl = posix_acl_dup(acl);
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ ext2_iset_acl(inode, &ei->i_acl, acl);
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ ext2_iset_acl(inode, &ei->i_default_acl, acl);
+ break;
+ }
}
return error;
}
-static int
-__ext2_permission(struct inode *inode, int mask, int lock)
+/*
+ * Inode operation permission().
+ *
+ * inode->i_sem: don't care
+ */
+int
+ext2_permission(struct inode *inode, int mask, struct nameidata *nd)
{
int mode = inode->i_mode;
@@ -254,29 +297,16 @@ __ext2_permission(struct inode *inode, int mask, int lock)
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
- /* ACL can't contain additional permissions if
- the ACL_MASK entry is 0 */
- if (!(mode & S_IRWXG))
- goto check_groups;
- if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED) {
- struct posix_acl *acl;
-
- if (lock) {
- down(&inode->i_sem);
- acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
- up(&inode->i_sem);
- } else
- acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
+ struct posix_acl *acl;
- if (IS_ERR(acl))
- return PTR_ERR(acl);
+ /* The access ACL cannot grant access if the group class
+ permission bits don't contain all requested permissions. */
+ if (((mode >> 3) & mask & S_IRWXO) != mask)
+ goto check_groups;
+ acl = ext2_get_acl(inode, ACL_TYPE_ACCESS);
+ if (acl) {
+ int error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
- if (EXT2_I(inode)->i_acl == EXT2_ACL_NOT_CACHED)
- return -EIO;
- }
- if (EXT2_I(inode)->i_acl) {
- int error = posix_acl_permission(inode,
- EXT2_I(inode)->i_acl, mask);
if (error == -EACCES)
goto check_capabilities;
return error;
@@ -303,32 +333,10 @@ check_capabilities:
}
/*
- * Inode operation permission().
- *
- * inode->i_sem: up
- * BKL held [before 2.5.x]
- */
-int
-ext2_permission(struct inode *inode, int mask)
-{
- return __ext2_permission(inode, mask, 1);
-}
-
-/*
- * Used internally if i_sem is already down.
- */
-int
-ext2_permission_locked(struct inode *inode, int mask)
-{
- return __ext2_permission(inode, mask, 0);
-}
-
-/*
* Initialize the ACLs of a new inode. Called from ext2_new_inode.
*
* dir->i_sem: down
* inode->i_sem: up (access to inode is still exclusive)
- * BKL held [before 2.5.x]
*/
int
ext2_init_acl(struct inode *inode, struct inode *dir)
@@ -388,7 +396,6 @@ cleanup:
* file mode.
*
* inode->i_sem: down
- * BKL held [before 2.5.x]
*/
int
ext2_acl_chmod(struct inode *inode)
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index 0cfbf4d1029b..01937daf1168 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -59,8 +59,7 @@ static inline int ext2_acl_count(size_t size)
#define EXT2_ACL_NOT_CACHED ((void *)-1)
/* acl.c */
-extern int ext2_permission (struct inode *, int);
-extern int ext2_permission_locked (struct inode *, int);
+extern int ext2_permission (struct inode *, int, struct nameidata *);
extern int ext2_acl_chmod (struct inode *);
extern int ext2_init_acl (struct inode *, struct inode *);
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 610695289845..67f704ab1258 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -41,6 +41,16 @@ struct ext2_inode_info {
__u32 i_prealloc_block;
__u32 i_prealloc_count;
__u32 i_dir_start_lookup;
+#ifdef CONFIG_EXT2_FS_XATTR
+ /*
+ * Extended attributes can be read independently of the main file
+ * data. Taking i_sem even when reading would cause contention
+ * between readers of EAs and writers of regular file data, so
+ * instead we synchronize on xattr_sem when reading or changing
+ * EAs.
+ */
+ struct rw_semaphore xattr_sem;
+#endif
#ifdef CONFIG_EXT2_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c
index af48364bcab8..107ff87b7208 100644
--- a/fs/ext2/ialloc.c
+++ b/fs/ext2/ialloc.c
@@ -489,17 +489,18 @@ found:
return group;
}
-struct inode * ext2_new_inode(struct inode * dir, int mode)
+struct inode *ext2_new_inode(struct inode *dir, int mode)
{
struct super_block *sb;
struct buffer_head *bitmap_bh = NULL;
struct buffer_head *bh2;
int group, i;
- ino_t ino;
+ ino_t ino = 0;
struct inode * inode;
- struct ext2_group_desc * desc;
- struct ext2_super_block * es;
+ struct ext2_group_desc *gdp;
+ struct ext2_super_block *es;
struct ext2_inode_info *ei;
+ struct ext2_sb_info *sbi;
int err;
sb = dir->i_sb;
@@ -508,36 +509,62 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
return ERR_PTR(-ENOMEM);
ei = EXT2_I(inode);
- es = EXT2_SB(sb)->s_es;
+ sbi = EXT2_SB(sb);
+ es = sbi->s_es;
repeat:
if (S_ISDIR(mode)) {
- if (test_opt (sb, OLDALLOC))
+ if (test_opt(sb, OLDALLOC))
group = find_group_dir(sb, dir);
else
group = find_group_orlov(sb, dir);
} else
group = find_group_other(sb, dir);
- err = -ENOSPC;
- if (group == -1)
+ if (group == -1) {
+ err = -ENOSPC;
goto fail;
+ }
- err = -EIO;
- bitmap_bh = read_inode_bitmap(sb, group);
- if (!bitmap_bh)
- goto fail2;
-
- i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data,
- EXT2_INODES_PER_GROUP(sb));
- if (i >= EXT2_INODES_PER_GROUP(sb))
- goto bad_count;
- if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
- i, (void *) bitmap_bh->b_data)) {
+ for (i = 0; i < sbi->s_groups_count; i++) {
+ gdp = ext2_get_group_desc(sb, group, &bh2);
brelse(bitmap_bh);
- ext2_release_inode(sb, group, S_ISDIR(mode));
- goto repeat;
+ bitmap_bh = read_inode_bitmap(sb, group);
+ if (!bitmap_bh) {
+ err = -EIO;
+ goto fail2;
+ }
+
+ i = ext2_find_first_zero_bit((unsigned long *)bitmap_bh->b_data,
+ EXT2_INODES_PER_GROUP(sb));
+ if (i >= EXT2_INODES_PER_GROUP(sb)) {
+ /*
+ * Rare race: find_group_xx() decided that there were
+ * free inodes in this group, but by the time we tried
+ * to allocate one, they're all gone. This can also
+ * occur because the counters which find_group_orlov()
+ * uses are approximate. So just go and search the
+ * next block group.
+ */
+ if (++group == sbi->s_groups_count)
+ group = 0;
+ continue;
+ }
+ if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group),
+ i, bitmap_bh->b_data)) {
+ brelse(bitmap_bh);
+ bitmap_bh = NULL;
+ ext2_release_inode(sb, group, S_ISDIR(mode));
+ goto repeat;
+ }
+ goto got;
}
+ /*
+ * Scanned all blockgroups.
+ */
+ err = -ENOSPC;
+ goto fail2;
+got:
mark_buffer_dirty(bitmap_bh);
if (sb->s_flags & MS_SYNCHRONOUS)
sync_dirty_buffer(bitmap_bh);
@@ -605,8 +632,9 @@ repeat:
inode->i_generation = EXT2_SB(sb)->s_next_generation++;
insert_inode_hash(inode);
- if(DQUOT_ALLOC_INODE(inode)) {
+ if (DQUOT_ALLOC_INODE(inode)) {
DQUOT_DROP(inode);
+ err = -ENOSPC;
goto fail3;
}
err = ext2_init_acl(inode, dir);
@@ -631,21 +659,6 @@ fail:
make_bad_inode(inode);
iput(inode);
return ERR_PTR(err);
-
-bad_count:
- brelse(bitmap_bh);
- ext2_error (sb, "ext2_new_inode",
- "Free inodes count corrupted in group %d",
- group);
- /* Is it really ENOSPC? */
- err = -ENOSPC;
- if (sb->s_flags & MS_RDONLY)
- goto fail;
-
- desc = ext2_get_group_desc (sb, group, &bh2);
- desc->bg_free_inodes_count = 0;
- mark_buffer_dirty(bh2);
- goto repeat;
}
unsigned long ext2_count_free_inodes (struct super_block * sb)
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 04489df5a2e5..52fb0eb666bf 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -66,7 +66,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
* Methods themselves.
*/
-static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode;
ino_t ino;
@@ -120,7 +120,7 @@ struct dentry *ext2_get_parent(struct dentry *child)
* If the create succeeds, we fill in the inode information
* with d_instantiate().
*/
-static int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
{
struct inode * inode = ext2_new_inode (dir, mode);
int err = PTR_ERR(inode);
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index c4604187f186..14b8cca47277 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -177,6 +177,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
rwlock_init(&ei->i_meta_lock);
+#ifdef CONFIG_EXT2_FS_XATTR
+ init_rwsem(&ei->xattr_sem);
+#endif
inode_init_once(&ei->vfs_inode);
}
}
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
index ed2d1d4e6671..f1334adc62ed 100644
--- a/fs/ext2/xattr.c
+++ b/fs/ext2/xattr.c
@@ -1,7 +1,7 @@
/*
* linux/fs/ext2/xattr.c
*
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher <agruen@suse.de>
*
* Fix by Harrison Xing <harrison@mountainviewdata.com>.
* Extended attributes for symlinks and special files added per
@@ -42,13 +42,12 @@
*
* Locking strategy
* ----------------
- * The VFS already holds the BKL and the inode->i_sem semaphore when any of
- * the xattr inode operations are called, so we are guaranteed that only one
- * processes accesses extended attributes of an inode at any time.
- *
- * For writing we also grab the ext2_xattr_sem semaphore. This ensures that
- * only a single process is modifying an extended attribute block, even
- * if the block is shared among inodes.
+ * EXT2_I(inode)->i_file_acl is protected by EXT2_I(inode)->xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count will change. Multiple writers to an EA block are synchronized
+ * by the bh lock. No more than a single bh lock is held at any time
+ * to avoid deadlocks.
*/
#include <linux/buffer_head.h>
@@ -57,7 +56,7 @@
#include <linux/slab.h>
#include <linux/mbcache.h>
#include <linux/quotaops.h>
-#include <asm/semaphore.h>
+#include <linux/rwsem.h>
#include "ext2.h"
#include "xattr.h"
#include "acl.h"
@@ -83,8 +82,9 @@ EXPORT_SYMBOL(ext2_xattr_set);
} while (0)
# define ea_bdebug(bh, f...) do { \
char b[BDEVNAME_SIZE]; \
- printk(KERN_DEBUG "block %s:%ld: ", \
- bdevname(bh->b_bdev, b), bh->b_blocknr); \
+ printk(KERN_DEBUG "block %s:%lu: ", \
+ bdevname(bh->b_bdev, b), \
+ (unsigned long) bh->b_blocknr); \
printk(f); \
printk("\n"); \
} while (0)
@@ -104,15 +104,6 @@ static void ext2_xattr_rehash(struct ext2_xattr_header *,
struct ext2_xattr_entry *);
static struct mb_cache *ext2_xattr_cache;
-
-/*
- * If a file system does not share extended attributes among inodes,
- * we should not need the ext2_xattr_sem semaphore. However, the
- * filesystem may still contain shared blocks, so we always take
- * the lock.
- */
-
-static DECLARE_MUTEX(ext2_xattr_sem);
static struct ext2_xattr_handler *ext2_xattr_handlers[EXT2_XATTR_INDEX_MAX];
static rwlock_t ext2_handler_lock = RW_LOCK_UNLOCKED;
@@ -195,8 +186,7 @@ ext2_xattr_handler(int name_index)
/*
* Inode operation getxattr()
*
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: don't care
*/
ssize_t
ext2_getxattr(struct dentry *dentry, const char *name,
@@ -214,8 +204,7 @@ ext2_getxattr(struct dentry *dentry, const char *name,
/*
* Inode operation listxattr()
*
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: don't care
*/
ssize_t
ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -226,8 +215,7 @@ ext2_listxattr(struct dentry *dentry, char *buffer, size_t size)
/*
* Inode operation setxattr()
*
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: down
*/
int
ext2_setxattr(struct dentry *dentry, const char *name,
@@ -247,8 +235,7 @@ ext2_setxattr(struct dentry *dentry, const char *name,
/*
* Inode operation removexattr()
*
- * dentry->d_inode->i_sem down
- * BKL held [before 2.5.x]
+ * dentry->d_inode->i_sem: down
*/
int
ext2_removexattr(struct dentry *dentry, const char *name)
@@ -278,21 +265,24 @@ ext2_xattr_get(struct inode *inode, int name_index, const char *name,
{
struct buffer_head *bh = NULL;
struct ext2_xattr_entry *entry;
- unsigned int size;
+ size_t name_len, size;
char *end;
- int name_len, error;
+ int error;
ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size);
if (name == NULL)
return -EINVAL;
+ down_read(&EXT2_I(inode)->xattr_sem);
+ error = -ENODATA;
if (!EXT2_I(inode)->i_file_acl)
- return -ENODATA;
+ goto cleanup;
ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
+ error = -EIO;
if (!bh)
- return -EIO;
+ goto cleanup;
ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
end = bh->b_data + bh->b_size;
@@ -357,6 +347,7 @@ found:
cleanup:
brelse(bh);
+ up_read(&EXT2_I(inode)->xattr_sem);
return error;
}
@@ -376,19 +367,22 @@ ext2_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
struct ext2_xattr_entry *entry;
- unsigned int size = 0;
+ size_t size = 0;
char *buf, *end;
int error;
ea_idebug(inode, "buffer=%p, buffer_size=%ld",
buffer, (long)buffer_size);
+ down_read(&EXT2_I(inode)->xattr_sem);
+ error = 0;
if (!EXT2_I(inode)->i_file_acl)
- return 0;
+ goto cleanup;
ea_idebug(inode, "reading block %d", EXT2_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
+ error = -EIO;
if (!bh)
- return -EIO;
+ goto cleanup;
ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
end = bh->b_data + bh->b_size;
@@ -441,6 +435,7 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
cleanup:
brelse(bh);
+ up_read(&EXT2_I(inode)->xattr_sem);
return error;
}
@@ -482,8 +477,8 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
struct buffer_head *bh = NULL;
struct ext2_xattr_header *header = NULL;
struct ext2_xattr_entry *here, *last;
- unsigned int name_len;
- int min_offs = sb->s_blocksize, not_found = 1, free, error;
+ size_t name_len, free, min_offs = sb->s_blocksize;
+ int not_found = 1, error;
char *end;
/*
@@ -512,8 +507,7 @@ ext2_xattr_set(struct inode *inode, int name_index, const char *name,
name_len = strlen(name);
if (name_len > 255 || value_len > sb->s_blocksize)
return -ERANGE;
- down(&ext2_xattr_sem);
-
+ down_write(&EXT2_I(inode)->xattr_sem);
if (EXT2_I(inode)->i_file_acl) {
/* The inode already has an extended attribute block. */
bh = sb_bread(sb, EXT2_I(inode)->i_file_acl);
@@ -540,7 +534,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
if ((char *)next >= end)
goto bad_block;
if (!here->e_value_block && here->e_value_size) {
- int offs = le16_to_cpu(here->e_value_offs);
+ size_t offs = le16_to_cpu(here->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
@@ -560,7 +554,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
if ((char *)next >= end)
goto bad_block;
if (!last->e_value_block && last->e_value_size) {
- int offs = le16_to_cpu(last->e_value_offs);
+ size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
@@ -584,36 +578,38 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
error = 0;
if (value == NULL)
goto cleanup;
- else
- free -= EXT2_XATTR_LEN(name_len);
} else {
/* Request to create an existing attribute? */
error = -EEXIST;
if (flags & XATTR_CREATE)
goto cleanup;
if (!here->e_value_block && here->e_value_size) {
- unsigned int size = le32_to_cpu(here->e_value_size);
+ size_t size = le32_to_cpu(here->e_value_size);
if (le16_to_cpu(here->e_value_offs) + size >
sb->s_blocksize || size > sb->s_blocksize)
goto bad_block;
free += EXT2_XATTR_SIZE(size);
}
+ free += EXT2_XATTR_LEN(name_len);
}
- free -= EXT2_XATTR_SIZE(value_len);
error = -ENOSPC;
- if (free < 0)
+ if (free < EXT2_XATTR_LEN(name_len) + EXT2_XATTR_SIZE(value_len))
goto cleanup;
/* Here we know that we can set the new attribute. */
if (header) {
+ /* assert(header == HDR(bh)); */
+ lock_buffer(bh);
if (header->h_refcount == cpu_to_le32(1)) {
ea_bdebug(bh, "modifying in-place");
ext2_xattr_cache_remove(bh);
+ /* keep the buffer locked while modifying it. */
} else {
int offset;
+ unlock_buffer(bh);
ea_bdebug(bh, "cloning");
header = kmalloc(bh->b_size, GFP_KERNEL);
error = -ENOMEM;
@@ -638,23 +634,36 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
last = here = ENTRY(header+1);
}
+ /* Iff we are modifying the block in-place, bh is locked here. */
+
if (not_found) {
/* Insert the new name. */
- int size = EXT2_XATTR_LEN(name_len);
- int rest = (char *)last - (char *)here;
+ size_t size = EXT2_XATTR_LEN(name_len);
+ size_t rest = (char *)last - (char *)here;
memmove((char *)here + size, here, rest);
memset(here, 0, size);
here->e_name_index = name_index;
here->e_name_len = name_len;
memcpy(here->e_name, name, name_len);
} else {
- /* Remove the old value. */
if (!here->e_value_block && here->e_value_size) {
char *first_val = (char *)header + min_offs;
- int offs = le16_to_cpu(here->e_value_offs);
+ size_t offs = le16_to_cpu(here->e_value_offs);
char *val = (char *)header + offs;
size_t size = EXT2_XATTR_SIZE(
le32_to_cpu(here->e_value_size));
+
+ if (size == EXT2_XATTR_SIZE(value_len)) {
+ /* The old and the new value have the same
+ size. Just replace. */
+ here->e_value_size = cpu_to_le32(value_len);
+ memset(val + size - EXT2_XATTR_PAD, 0,
+ EXT2_XATTR_PAD); /* Clear pad bytes. */
+ memcpy(val, value, value_len);
+ goto skip_replace;
+ }
+
+ /* Remove the old value. */
memmove(first_val + size, first_val, val - first_val);
memset(first_val, 0, size);
here->e_value_offs = 0;
@@ -663,7 +672,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
/* Adjust all value offsets. */
last = ENTRY(header+1);
while (!IS_LAST_ENTRY(last)) {
- int o = le16_to_cpu(last->e_value_offs);
+ size_t o = le16_to_cpu(last->e_value_offs);
if (!last->e_value_block && o < offs)
last->e_value_offs =
cpu_to_le16(o + size);
@@ -671,19 +680,12 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
}
}
if (value == NULL) {
- /* Remove this attribute. */
- if (EXT2_XATTR_NEXT(ENTRY(header+1)) == last) {
- /* This block is now empty. */
- error = ext2_xattr_set2(inode, bh, NULL);
- goto cleanup;
- } else {
- /* Remove the old name. */
- int size = EXT2_XATTR_LEN(name_len);
- last = ENTRY((char *)last - size);
- memmove(here, (char*)here + size,
- (char*)last - (char*)here);
- memset(last, 0, size);
- }
+ /* Remove the old name. */
+ size_t size = EXT2_XATTR_LEN(name_len);
+ last = ENTRY((char *)last - size);
+ memmove(here, (char*)here + size,
+ (char*)last - (char*)here);
+ memset(last, 0, size);
}
}
@@ -700,15 +702,25 @@ bad_block: ext2_error(sb, "ext2_xattr_set",
memcpy(val, value, value_len);
}
}
- ext2_xattr_rehash(header, here);
- error = ext2_xattr_set2(inode, bh, header);
+skip_replace:
+ if (IS_LAST_ENTRY(ENTRY(header+1))) {
+ /* This block is now empty. */
+ if (bh && header == HDR(bh))
+ unlock_buffer(bh); /* we were modifying in-place. */
+ error = ext2_xattr_set2(inode, bh, NULL);
+ } else {
+ ext2_xattr_rehash(header, here);
+ if (bh && header == HDR(bh))
+ unlock_buffer(bh); /* we were modifying in-place. */
+ error = ext2_xattr_set2(inode, bh, header);
+ }
cleanup:
brelse(bh);
if (!(bh && header == HDR(bh)))
kfree(header);
- up(&ext2_xattr_sem);
+ up_write(&EXT2_I(inode)->xattr_sem);
return error;
}
@@ -728,31 +740,37 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
new_bh = ext2_xattr_cache_find(inode, header);
if (new_bh) {
/*
- * We found an identical block in the cache.
- * The old block will be released after updating
- * the inode.
+ * We found an identical block in the cache. The
+ * block returned is locked. The old block will
+ * be released after updating the inode.
*/
- ea_bdebug(new_bh, "%s block %ld",
+ ea_bdebug(new_bh, "%s block %lu",
(old_bh == new_bh) ? "keeping" : "reusing",
- new_bh->b_blocknr);
+ (unsigned long) new_bh->b_blocknr);
error = -EDQUOT;
- if (DQUOT_ALLOC_BLOCK(inode, 1))
+ if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+ unlock_buffer(new_bh);
goto cleanup;
+ }
HDR(new_bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
ea_bdebug(new_bh, "refcount now=%d",
le32_to_cpu(HDR(new_bh)->h_refcount));
+ unlock_buffer(new_bh);
} else if (old_bh && header == HDR(old_bh)) {
- /* Keep this block. */
+ /* Keep this block. No need to lock the block as we
+ don't need to change the reference count. */
new_bh = old_bh;
get_bh(new_bh);
ext2_xattr_cache_insert(new_bh);
} else {
/* We need to allocate a new block */
- int goal = le32_to_cpu(EXT2_SB(sb)->s_es->s_first_data_block) +
- EXT2_I(inode)->i_block_group * EXT2_BLOCKS_PER_GROUP(sb);
+ int goal = le32_to_cpu(EXT2_SB(sb)->s_es->
+ s_first_data_block) +
+ EXT2_I(inode)->i_block_group *
+ EXT2_BLOCKS_PER_GROUP(sb);
int block = ext2_new_block(inode, goal, 0, 0, &error);
if (error)
goto cleanup;
@@ -794,12 +812,11 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
error = 0;
if (old_bh && old_bh != new_bh) {
/*
- * If there was an old block, and we are not still using it,
- * we now release the old block.
- */
- unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-
- if (refcount == 1) {
+ * If there was an old block and we are no longer using it,
+ * release the old block.
+ */
+ lock_buffer(old_bh);
+ if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
/* Free the old block. */
ea_bdebug(old_bh, "freeing");
ext2_free_blocks(inode, old_bh->b_blocknr, 1);
@@ -809,12 +826,14 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
bforget(old_bh);
} else {
/* Decrement the refcount only. */
- refcount--;
- HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
+ HDR(old_bh)->h_refcount = cpu_to_le32(
+ le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
DQUOT_FREE_BLOCK(inode, 1);
mark_buffer_dirty(old_bh);
- ea_bdebug(old_bh, "refcount now=%d", refcount);
+ ea_bdebug(old_bh, "refcount now=%d",
+ le32_to_cpu(HDR(old_bh)->h_refcount));
}
+ unlock_buffer(old_bh);
}
cleanup:
@@ -832,12 +851,11 @@ cleanup:
void
ext2_xattr_delete_inode(struct inode *inode)
{
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
+ down_write(&EXT2_I(inode)->xattr_sem);
if (!EXT2_I(inode)->i_file_acl)
- return;
- down(&ext2_xattr_sem);
-
+ goto cleanup;
bh = sb_bread(inode->i_sb, EXT2_I(inode)->i_file_acl);
if (!bh) {
ext2_error(inode->i_sb, "ext2_xattr_delete_inode",
@@ -853,12 +871,12 @@ ext2_xattr_delete_inode(struct inode *inode)
EXT2_I(inode)->i_file_acl);
goto cleanup;
}
- ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+ lock_buffer(bh);
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
ext2_xattr_cache_remove(bh);
ext2_free_blocks(inode, EXT2_I(inode)->i_file_acl, 1);
+ get_bh(bh);
bforget(bh);
- bh = NULL;
} else {
HDR(bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(bh)->h_refcount) - 1);
@@ -867,11 +885,13 @@ ext2_xattr_delete_inode(struct inode *inode)
sync_dirty_buffer(bh);
DQUOT_FREE_BLOCK(inode, 1);
}
+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+ unlock_buffer(bh);
EXT2_I(inode)->i_file_acl = 0;
cleanup:
brelse(bh);
- up(&ext2_xattr_sem);
+ up_write(&EXT2_I(inode)->xattr_sem);
}
/*
@@ -964,8 +984,8 @@ ext2_xattr_cmp(struct ext2_xattr_header *header1,
*
* Find an identical extended attribute block.
*
- * Returns a pointer to the block found, or NULL if such a block was
- * not found or an error occurred.
+ * Returns a locked buffer head to the block found, or NULL if such
+ * a block was not found or an error occurred.
*/
static struct buffer_head *
ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
@@ -976,7 +996,8 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
if (!header->h_hash)
return NULL; /* never share */
ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
- ce = mb_cache_entry_find_first(ext2_xattr_cache, 0, inode->i_bdev, hash);
+ ce = mb_cache_entry_find_first(ext2_xattr_cache, 0,
+ inode->i_sb->s_bdev, hash);
while (ce) {
struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
@@ -984,19 +1005,24 @@ ext2_xattr_cache_find(struct inode *inode, struct ext2_xattr_header *header)
ext2_error(inode->i_sb, "ext2_xattr_cache_find",
"inode %ld: block %ld read error",
inode->i_ino, (unsigned long) ce->e_block);
- } else if (le32_to_cpu(HDR(bh)->h_refcount) >
- EXT2_XATTR_REFCOUNT_MAX) {
- ea_idebug(inode, "block %ld refcount %d>%d",
- (unsigned long) ce->e_block,
- le32_to_cpu(HDR(bh)->h_refcount),
- EXT2_XATTR_REFCOUNT_MAX);
- } else if (!ext2_xattr_cmp(header, HDR(bh))) {
- ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
- mb_cache_entry_release(ce);
- return bh;
+ } else {
+ lock_buffer(bh);
+ if (le32_to_cpu(HDR(bh)->h_refcount) >
+ EXT2_XATTR_REFCOUNT_MAX) {
+ ea_idebug(inode, "block %ld refcount %d>%d",
+ (unsigned long) ce->e_block,
+ le32_to_cpu(HDR(bh)->h_refcount),
+ EXT2_XATTR_REFCOUNT_MAX);
+ } else if (!ext2_xattr_cmp(header, HDR(bh))) {
+ ea_bdebug(bh, "b_count=%d",
+ atomic_read(&(bh->b_count)));
+ mb_cache_entry_release(ce);
+ return bh;
+ }
+ unlock_buffer(bh);
+ brelse(bh);
}
- brelse(bh);
- ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
+ ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
}
return NULL;
}
diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
index 027beb89c7e0..be1558761064 100644
--- a/fs/ext2/xattr_user.c
+++ b/fs/ext2/xattr_user.c
@@ -11,10 +11,6 @@
#include "ext2.h"
#include "xattr.h"
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
-# include "acl.h"
-#endif
-
#define XATTR_USER_PREFIX "user."
static size_t
@@ -44,11 +40,7 @@ ext2_xattr_user_get(struct inode *inode, const char *name,
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
- error = ext2_permission_locked(inode, MAY_READ);
-#else
- error = permission(inode, MAY_READ);
-#endif
+ error = permission(inode, MAY_READ, NULL);
if (error)
return error;
@@ -68,11 +60,7 @@ ext2_xattr_user_set(struct inode *inode, const char *name,
if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM;
-#ifdef CONFIG_EXT2_FS_POSIX_ACL
- error = ext2_permission_locked(inode, MAY_WRITE);
-#else
- error = permission(inode, MAY_WRITE);
-#endif
+ error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 9313430093c5..2416e214280f 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -1,7 +1,7 @@
/*
* linux/fs/ext3/acl.c
*
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*/
#include <linux/init.h>
@@ -20,7 +20,7 @@ static struct posix_acl *
ext3_acl_from_disk(const void *value, size_t size)
{
const char *end = (char *)value + size;
- int n, count;
+ size_t n, count;
struct posix_acl *acl;
if (!value)
@@ -86,7 +86,7 @@ ext3_acl_to_disk(const struct posix_acl *acl, size_t *size)
{
ext3_acl_header *ext_acl;
char *e;
- int n;
+ size_t n;
*size = ext3_acl_size(acl->a_count);
ext_acl = (ext3_acl_header *)kmalloc(sizeof(ext3_acl_header) +
@@ -125,18 +125,43 @@ fail:
return ERR_PTR(-EINVAL);
}
+static inline struct posix_acl *
+ext3_iget_acl(struct inode *inode, struct posix_acl **i_acl)
+{
+ struct posix_acl *acl = EXT3_ACL_NOT_CACHED;
+
+ spin_lock(&inode->i_lock);
+ if (*i_acl != EXT3_ACL_NOT_CACHED)
+ acl = posix_acl_dup(*i_acl);
+ spin_unlock(&inode->i_lock);
+
+ return acl;
+}
+
+static inline void
+ext3_iset_acl(struct inode *inode, struct posix_acl **i_acl,
+ struct posix_acl *acl)
+{
+ spin_lock(&inode->i_lock);
+ if (*i_acl != EXT3_ACL_NOT_CACHED)
+ posix_acl_release(*i_acl);
+ *i_acl = posix_acl_dup(acl);
+ spin_unlock(&inode->i_lock);
+}
+
/*
* Inode operation get_posix_acl().
*
- * inode->i_sem: down
+ * inode->i_sem: don't care
*/
static struct posix_acl *
ext3_get_acl(struct inode *inode, int type)
{
+ const size_t max_size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+ struct ext3_inode_info *ei = EXT3_I(inode);
int name_index;
char *value;
- struct posix_acl *acl, **p_acl;
- const size_t size = ext3_acl_size(EXT3_ACL_MAX_ENTRIES);
+ struct posix_acl *acl;
int retval;
if (!test_opt(inode->i_sb, POSIX_ACL))
@@ -144,36 +169,45 @@ ext3_get_acl(struct inode *inode, int type)
switch(type) {
case ACL_TYPE_ACCESS:
- p_acl = &EXT3_I(inode)->i_acl;
+ acl = ext3_iget_acl(inode, &ei->i_acl);
+ if (acl != EXT3_ACL_NOT_CACHED)
+ return acl;
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
- p_acl = &EXT3_I(inode)->i_default_acl;
+ acl = ext3_iget_acl(inode, &ei->i_default_acl);
+ if (acl != EXT3_ACL_NOT_CACHED)
+ return acl;
name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
return ERR_PTR(-EINVAL);
}
- if (*p_acl != EXT3_ACL_NOT_CACHED)
- return posix_acl_dup(*p_acl);
- value = kmalloc(size, GFP_KERNEL);
+ value = kmalloc(max_size, GFP_KERNEL);
if (!value)
return ERR_PTR(-ENOMEM);
- retval = ext3_xattr_get(inode, name_index, "", value, size);
-
- if (retval == -ENODATA || retval == -ENOSYS)
- *p_acl = acl = NULL;
- else if (retval < 0)
- acl = ERR_PTR(retval);
- else {
+ retval = ext3_xattr_get(inode, name_index, "", value, max_size);
+ acl = ERR_PTR(retval);
+ if (retval > 0)
acl = ext3_acl_from_disk(value, retval);
- if (!IS_ERR(acl))
- *p_acl = posix_acl_dup(acl);
- }
+ else if (retval == -ENODATA || retval == -ENOSYS)
+ acl = NULL;
kfree(value);
+
+ if (!IS_ERR(acl)) {
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ ext3_iset_acl(inode, &ei->i_acl, acl);
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ ext3_iset_acl(inode, &ei->i_default_acl, acl);
+ break;
+ }
+ }
return acl;
}
@@ -186,9 +220,9 @@ static int
ext3_set_acl(handle_t *handle, struct inode *inode, int type,
struct posix_acl *acl)
{
+ struct ext3_inode_info *ei = EXT3_I(inode);
int name_index;
void *value = NULL;
- struct posix_acl **p_acl;
size_t size;
int error;
@@ -198,7 +232,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
switch(type) {
case ACL_TYPE_ACCESS:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
- p_acl = &EXT3_I(inode)->i_acl;
if (acl) {
mode_t mode = inode->i_mode;
error = posix_acl_equiv_mode(acl, &mode);
@@ -215,7 +248,6 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
case ACL_TYPE_DEFAULT:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
- p_acl = &EXT3_I(inode)->i_default_acl;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
break;
@@ -231,20 +263,32 @@ ext3_set_acl(handle_t *handle, struct inode *inode, int type,
return (int)PTR_ERR(value);
}
- error = ext3_xattr_set_handle(handle, inode, name_index, "", value, size, 0);
+ error = ext3_xattr_set_handle(handle, inode, name_index, "",
+ value, size, 0);
if (value)
kfree(value);
if (!error) {
- if (*p_acl && *p_acl != EXT3_ACL_NOT_CACHED)
- posix_acl_release(*p_acl);
- *p_acl = posix_acl_dup(acl);
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ ext3_iset_acl(inode, &ei->i_acl, acl);
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ ext3_iset_acl(inode, &ei->i_default_acl, acl);
+ break;
+ }
}
return error;
}
-static int
-__ext3_permission(struct inode *inode, int mask, int lock)
+/*
+ * Inode operation permission().
+ *
+ * inode->i_sem: don't care
+ */
+int
+ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
{
int mode = inode->i_mode;
@@ -258,29 +302,16 @@ __ext3_permission(struct inode *inode, int mask, int lock)
if (current->fsuid == inode->i_uid) {
mode >>= 6;
} else if (test_opt(inode->i_sb, POSIX_ACL)) {
- /* ACL can't contain additional permissions if
- the ACL_MASK entry is 0 */
- if (!(mode & S_IRWXG))
- goto check_groups;
- if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED) {
- struct posix_acl *acl;
-
- if (lock) {
- down(&inode->i_sem);
- acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
- up(&inode->i_sem);
- } else
- acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
+ struct posix_acl *acl;
- if (IS_ERR(acl))
- return PTR_ERR(acl);
+ /* The access ACL cannot grant access if the group class
+ permission bits don't contain all requested permissions. */
+ if (((mode >> 3) & mask & S_IRWXO) != mask)
+ goto check_groups;
+ acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
+ if (acl) {
+ int error = posix_acl_permission(inode, acl, mask);
posix_acl_release(acl);
- if (EXT3_I(inode)->i_acl == EXT3_ACL_NOT_CACHED)
- return -EIO;
- }
- if (EXT3_I(inode)->i_acl) {
- int error = posix_acl_permission(inode,
- EXT3_I(inode)->i_acl, mask);
if (error == -EACCES)
goto check_capabilities;
return error;
@@ -307,26 +338,6 @@ check_capabilities:
}
/*
- * Inode operation permission().
- *
- * inode->i_sem: up
- */
-int
-ext3_permission(struct inode *inode, int mask)
-{
- return __ext3_permission(inode, mask, 1);
-}
-
-/*
- * Used internally if i_sem is already down.
- */
-int
-ext3_permission_locked(struct inode *inode, int mask)
-{
- return __ext3_permission(inode, mask, 0);
-}
-
-/*
* Initialize the ACLs of a new inode. Called from ext3_new_inode.
*
* dir->i_sem: down
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index e0962a6c24b2..9d9d9d2e4a0c 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -59,8 +59,7 @@ static inline int ext3_acl_count(size_t size)
#define EXT3_ACL_NOT_CACHED ((void *)-1)
/* acl.c */
-extern int ext3_permission (struct inode *, int);
-extern int ext3_permission_locked (struct inode *, int);
+extern int ext3_permission (struct inode *, int, struct nameidata *);
extern int ext3_acl_chmod (struct inode *);
extern int ext3_init_acl (handle_t *, struct inode *, struct inode *);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index c2b0304b1855..aa632b07899a 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -2290,68 +2290,72 @@ out_stop:
ext3_journal_stop(handle);
}
-/*
- * ext3_get_inode_loc returns with an extra refcount against the
- * inode's underlying buffer_head on success.
- */
-
-int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+static unsigned long ext3_get_inode_block(struct super_block *sb,
+ unsigned long ino, struct ext3_iloc *iloc)
{
- struct buffer_head *bh = 0;
- unsigned long block;
- unsigned long block_group;
- unsigned long group_desc;
- unsigned long desc;
- unsigned long offset;
+ unsigned long desc, group_desc, block_group;
+ unsigned long offset, block;
+ struct buffer_head *bh;
struct ext3_group_desc * gdp;
- if ((inode->i_ino != EXT3_ROOT_INO &&
- inode->i_ino != EXT3_JOURNAL_INO &&
- inode->i_ino < EXT3_FIRST_INO(inode->i_sb)) ||
- inode->i_ino > le32_to_cpu(
- EXT3_SB(inode->i_sb)->s_es->s_inodes_count)) {
- ext3_error (inode->i_sb, "ext3_get_inode_loc",
- "bad inode number: %lu", inode->i_ino);
- goto bad_inode;
+ if ((ino != EXT3_ROOT_INO &&
+ ino != EXT3_JOURNAL_INO &&
+ ino < EXT3_FIRST_INO(sb)) ||
+ ino > le32_to_cpu(
+ EXT3_SB(sb)->s_es->s_inodes_count)) {
+ ext3_error (sb, "ext3_get_inode_block",
+ "bad inode number: %lu", ino);
+ return 0;
}
- block_group = (inode->i_ino - 1) / EXT3_INODES_PER_GROUP(inode->i_sb);
- if (block_group >= EXT3_SB(inode->i_sb)->s_groups_count) {
- ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb);
+ if (block_group >= EXT3_SB(sb)->s_groups_count) {
+ ext3_error (sb, "ext3_get_inode_block",
"group >= groups count");
- goto bad_inode;
+ return 0;
}
- group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(inode->i_sb);
- desc = block_group & (EXT3_DESC_PER_BLOCK(inode->i_sb) - 1);
- bh = EXT3_SB(inode->i_sb)->s_group_desc[group_desc];
+ group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
+ desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
+ bh = EXT3_SB(sb)->s_group_desc[group_desc];
if (!bh) {
- ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ ext3_error (sb, "ext3_get_inode_block",
"Descriptor not loaded");
- goto bad_inode;
+ return 0;
}
gdp = (struct ext3_group_desc *) bh->b_data;
/*
* Figure out the offset within the block group inode table
*/
- offset = ((inode->i_ino - 1) % EXT3_INODES_PER_GROUP(inode->i_sb)) *
- EXT3_INODE_SIZE(inode->i_sb);
+ offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
+ EXT3_INODE_SIZE(sb);
block = le32_to_cpu(gdp[desc].bg_inode_table) +
- (offset >> EXT3_BLOCK_SIZE_BITS(inode->i_sb));
- if (!(bh = sb_bread(inode->i_sb, block))) {
- ext3_error (inode->i_sb, "ext3_get_inode_loc",
- "unable to read inode block - "
- "inode=%lu, block=%lu", inode->i_ino, block);
- goto bad_inode;
- }
- offset &= (EXT3_BLOCK_SIZE(inode->i_sb) - 1);
+ (offset >> EXT3_BLOCK_SIZE_BITS(sb));
- iloc->bh = bh;
- iloc->raw_inode = (struct ext3_inode *) (bh->b_data + offset);
iloc->block_group = block_group;
+ iloc->offset = offset & (EXT3_BLOCK_SIZE(sb) - 1);
+ return block;
+}
- return 0;
+/*
+ * ext3_get_inode_loc returns with an extra refcount against the
+ * inode's underlying buffer_head on success.
+ */
+
+int ext3_get_inode_loc (struct inode *inode, struct ext3_iloc *iloc)
+{
+ unsigned long block;
- bad_inode:
+ block = ext3_get_inode_block(inode->i_sb, inode->i_ino, iloc);
+ if (block) {
+ struct buffer_head *bh = sb_bread(inode->i_sb, block);
+ if (bh) {
+ iloc->bh = bh;
+ return 0;
+ }
+ ext3_error (inode->i_sb, "ext3_get_inode_loc",
+ "unable to read inode block - "
+ "inode=%lu, block=%lu", inode->i_ino, block);
+ }
return -EIO;
}
@@ -2388,7 +2392,7 @@ void ext3_read_inode(struct inode * inode)
if (ext3_get_inode_loc(inode, &iloc))
goto bad_inode;
bh = iloc.bh;
- raw_inode = iloc.raw_inode;
+ raw_inode = ext3_raw_inode(&iloc);
inode->i_mode = le16_to_cpu(raw_inode->i_mode);
inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);
inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);
@@ -2454,11 +2458,9 @@ void ext3_read_inode(struct inode * inode)
* even on big-endian machines: we do NOT byteswap the block numbers!
*/
for (block = 0; block < EXT3_N_BLOCKS; block++)
- ei->i_data[block] = iloc.raw_inode->i_block[block];
+ ei->i_data[block] = raw_inode->i_block[block];
INIT_LIST_HEAD(&ei->i_orphan);
- brelse (iloc.bh);
-
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext3_file_inode_operations;
inode->i_fop = &ext3_file_operations;
@@ -2476,8 +2478,9 @@ void ext3_read_inode(struct inode * inode)
} else {
inode->i_op = &ext3_special_inode_operations;
init_special_inode(inode, inode->i_mode,
- le32_to_cpu(iloc.raw_inode->i_block[0]));
+ le32_to_cpu(raw_inode->i_block[0]));
}
+ brelse (iloc.bh);
ext3_set_inode_flags(inode);
return;
@@ -2497,7 +2500,7 @@ static int ext3_do_update_inode(handle_t *handle,
struct inode *inode,
struct ext3_iloc *iloc)
{
- struct ext3_inode *raw_inode = iloc->raw_inode;
+ struct ext3_inode *raw_inode = ext3_raw_inode(iloc);
struct ext3_inode_info *ei = EXT3_I(inode);
struct buffer_head *bh = iloc->bh;
int err = 0, rc, block;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index ae995cad505a..74e53bcc480e 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -970,7 +970,7 @@ errout:
}
#endif
-static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode;
struct ext3_dir_entry_2 * de;
@@ -1623,7 +1623,8 @@ static int ext3_add_nondir(handle_t *handle,
* If the create succeeds, we fill in the inode information
* with d_instantiate().
*/
-static int ext3_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
+ struct nameidata *nd)
{
handle_t *handle;
struct inode * inode;
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index d84dddf2959b..04f3c6d04b7f 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -519,6 +519,9 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR) {
INIT_LIST_HEAD(&ei->i_orphan);
+#ifdef CONFIG_EXT3_FS_XATTR
+ init_rwsem(&ei->xattr_sem);
+#endif
init_rwsem(&ei->truncate_sem);
inode_init_once(&ei->vfs_inode);
}
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 066316459d83..6fbda077bdbe 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1,7 +1,7 @@
/*
* linux/fs/ext3/xattr.c
*
- * Copyright (C) 2001 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ * Copyright (C) 2001-2003 Andreas Gruenbacher, <agruen@suse.de>
*
* Fix by Harrison Xing <harrison@mountainviewdata.com>.
* Ext3 code with a lot of help from Eric Jarman <ejarman@acm.org>.
@@ -43,13 +43,12 @@
*
* Locking strategy
* ----------------
- * The VFS holdsinode->i_sem semaphore when any of the xattr inode
- * operations are called, so we are guaranteed that only one
- * processes accesses extended attributes of an inode at any time.
- *
- * For writing we also grab the ext3_xattr_sem semaphore. This ensures that
- * only a single process is modifying an extended attribute block, even
- * if the block is shared among inodes.
+ * EXT3_I(inode)->i_file_acl is protected by EXT3_I(inode)->xattr_sem.
+ * EA blocks are only changed if they are exclusive to an inode, so
+ * holding xattr_sem also means that nothing but the EA block's reference
+ * count will change. Multiple writers to an EA block are synchronized
+ * by the bh lock. No more than a single bh lock is held at any time
+ * to avoid deadlocks.
*/
#include <linux/init.h>
@@ -59,12 +58,10 @@
#include <linux/ext3_fs.h>
#include <linux/mbcache.h>
#include <linux/quotaops.h>
-#include <asm/semaphore.h>
+#include <linux/rwsem.h>
#include "xattr.h"
#include "acl.h"
-#define EXT3_EA_USER "user."
-
#define HDR(bh) ((struct ext3_xattr_header *)((bh)->b_data))
#define ENTRY(ptr) ((struct ext3_xattr_entry *)(ptr))
#define FIRST_ENTRY(bh) ENTRY(HDR(bh)+1)
@@ -79,8 +76,9 @@
} while (0)
# define ea_bdebug(bh, f...) do { \
char b[BDEVNAME_SIZE]; \
- printk(KERN_DEBUG "block %s:%ld: ", \
- bdevname(bh->b_bdev, b), bh->b_blocknr); \
+ printk(KERN_DEBUG "block %s:%lu: ", \
+ bdevname(bh->b_bdev, b), \
+ (unsigned long) bh->b_blocknr); \
printk(f); \
printk("\n"); \
} while (0)
@@ -94,22 +92,14 @@ static int ext3_xattr_set_handle2(handle_t *, struct inode *,
struct ext3_xattr_header *);
static int ext3_xattr_cache_insert(struct buffer_head *);
-static struct buffer_head *ext3_xattr_cache_find(struct inode *,
- struct ext3_xattr_header *);
+static struct buffer_head *ext3_xattr_cache_find(handle_t *, struct inode *,
+ struct ext3_xattr_header *,
+ int *);
static void ext3_xattr_cache_remove(struct buffer_head *);
static void ext3_xattr_rehash(struct ext3_xattr_header *,
struct ext3_xattr_entry *);
static struct mb_cache *ext3_xattr_cache;
-
-/*
- * If a file system does not share extended attributes among inodes,
- * we should not need the ext3_xattr_sem semaphore. However, the
- * filesystem may still contain shared blocks, so we always take
- * the lock.
- */
-
-static DECLARE_MUTEX(ext3_xattr_sem);
static struct ext3_xattr_handler *ext3_xattr_handlers[EXT3_XATTR_INDEX_MAX];
static rwlock_t ext3_handler_lock = RW_LOCK_UNLOCKED;
@@ -192,7 +182,7 @@ ext3_xattr_handler(int name_index)
/*
* Inode operation getxattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: don't care
*/
ssize_t
ext3_getxattr(struct dentry *dentry, const char *name,
@@ -210,7 +200,7 @@ ext3_getxattr(struct dentry *dentry, const char *name,
/*
* Inode operation listxattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: don't care
*/
ssize_t
ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
@@ -221,7 +211,7 @@ ext3_listxattr(struct dentry *dentry, char *buffer, size_t size)
/*
* Inode operation setxattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: down
*/
int
ext3_setxattr(struct dentry *dentry, const char *name,
@@ -241,7 +231,7 @@ ext3_setxattr(struct dentry *dentry, const char *name,
/*
* Inode operation removexattr()
*
- * dentry->d_inode->i_sem down
+ * dentry->d_inode->i_sem: down
*/
int
ext3_removexattr(struct dentry *dentry, const char *name)
@@ -271,21 +261,24 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name,
{
struct buffer_head *bh = NULL;
struct ext3_xattr_entry *entry;
- unsigned int size;
+ size_t name_len, size;
char *end;
- int name_len, error;
+ int error;
ea_idebug(inode, "name=%d.%s, buffer=%p, buffer_size=%ld",
name_index, name, buffer, (long)buffer_size);
if (name == NULL)
return -EINVAL;
+ down_read(&EXT3_I(inode)->xattr_sem);
+ error = -ENODATA;
if (!EXT3_I(inode)->i_file_acl)
- return -ENODATA;
+ goto cleanup;
ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
+ error = -EIO;
if (!bh)
- return -EIO;
+ goto cleanup;
ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
end = bh->b_data + bh->b_size;
@@ -350,6 +343,7 @@ found:
cleanup:
brelse(bh);
+ up_read(&EXT3_I(inode)->xattr_sem);
return error;
}
@@ -369,19 +363,22 @@ ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size)
{
struct buffer_head *bh = NULL;
struct ext3_xattr_entry *entry;
- unsigned int size = 0;
+ size_t size = 0;
char *buf, *end;
int error;
ea_idebug(inode, "buffer=%p, buffer_size=%ld",
buffer, (long)buffer_size);
+ down_read(&EXT3_I(inode)->xattr_sem);
+ error = 0;
if (!EXT3_I(inode)->i_file_acl)
- return 0;
+ goto cleanup;
ea_idebug(inode, "reading block %d", EXT3_I(inode)->i_file_acl);
bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
+ error = -EIO;
if (!bh)
- return -EIO;
+ goto cleanup;
ea_bdebug(bh, "b_count=%d, refcount=%d",
atomic_read(&(bh->b_count)), le32_to_cpu(HDR(bh)->h_refcount));
end = bh->b_data + bh->b_size;
@@ -434,6 +431,7 @@ bad_block: ext3_error(inode->i_sb, "ext3_xattr_list",
cleanup:
brelse(bh);
+ up_read(&EXT3_I(inode)->xattr_sem);
return error;
}
@@ -449,11 +447,12 @@ static void ext3_xattr_update_super_block(handle_t *handle,
return;
lock_super(sb);
- ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh);
- EXT3_SB(sb)->s_es->s_feature_compat |=
- cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
- sb->s_dirt = 1;
- ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ if (ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh) == 0) {
+ EXT3_SB(sb)->s_es->s_feature_compat |=
+ cpu_to_le32(EXT3_FEATURE_COMPAT_EXT_ATTR);
+ sb->s_dirt = 1;
+ ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
+ }
unlock_super(sb);
}
@@ -478,8 +477,8 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
struct buffer_head *bh = NULL;
struct ext3_xattr_header *header = NULL;
struct ext3_xattr_entry *here, *last;
- unsigned int name_len;
- int min_offs = sb->s_blocksize, not_found = 1, free, error;
+ size_t name_len, free, min_offs = sb->s_blocksize;
+ int not_found = 1, error;
char *end;
/*
@@ -508,8 +507,7 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index,
name_len = strlen(name);
if (name_len > 255 || value_len > sb->s_blocksize)
return -ERANGE;
- down(&ext3_xattr_sem);
-
+ down_write(&EXT3_I(inode)->xattr_sem);
if (EXT3_I(inode)->i_file_acl) {
/* The inode already has an extended attribute block. */
bh = sb_bread(sb, EXT3_I(inode)->i_file_acl);
@@ -536,7 +534,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
if ((char *)next >= end)
goto bad_block;
if (!here->e_value_block && here->e_value_size) {
- int offs = le16_to_cpu(here->e_value_offs);
+ size_t offs = le16_to_cpu(here->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
@@ -556,7 +554,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
if ((char *)next >= end)
goto bad_block;
if (!last->e_value_block && last->e_value_size) {
- int offs = le16_to_cpu(last->e_value_offs);
+ size_t offs = le16_to_cpu(last->e_value_offs);
if (offs < min_offs)
min_offs = offs;
}
@@ -580,39 +578,50 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
error = 0;
if (value == NULL)
goto cleanup;
- else
- free -= EXT3_XATTR_LEN(name_len);
} else {
/* Request to create an existing attribute? */
error = -EEXIST;
if (flags & XATTR_CREATE)
goto cleanup;
if (!here->e_value_block && here->e_value_size) {
- unsigned int size = le32_to_cpu(here->e_value_size);
+ size_t size = le32_to_cpu(here->e_value_size);
if (le16_to_cpu(here->e_value_offs) + size >
sb->s_blocksize || size > sb->s_blocksize)
goto bad_block;
free += EXT3_XATTR_SIZE(size);
}
+ free += EXT3_XATTR_LEN(name_len);
}
- free -= EXT3_XATTR_SIZE(value_len);
error = -ENOSPC;
- if (free < 0)
+ if (free < EXT3_XATTR_LEN(name_len) + EXT3_XATTR_SIZE(value_len))
goto cleanup;
/* Here we know that we can set the new attribute. */
if (header) {
+ int credits = 0;
+
+ /* assert(header == HDR(bh)); */
+ if (header->h_refcount != cpu_to_le32(1))
+ goto skip_get_write_access;
+ /* ext3_journal_get_write_access() requires an unlocked bh,
+ which complicates things here. */
+ error = ext3_journal_get_write_access_credits(handle, bh,
+ &credits);
+ if (error)
+ goto cleanup;
+ lock_buffer(bh);
if (header->h_refcount == cpu_to_le32(1)) {
ea_bdebug(bh, "modifying in-place");
ext3_xattr_cache_remove(bh);
- error = ext3_journal_get_write_access(handle, bh);
- if (error)
- goto cleanup;
+ /* keep the buffer locked while modifying it. */
} else {
int offset;
+ unlock_buffer(bh);
+ journal_release_buffer(handle, bh, credits);
+ skip_get_write_access:
ea_bdebug(bh, "cloning");
header = kmalloc(bh->b_size, GFP_KERNEL);
error = -ENOMEM;
@@ -637,23 +646,36 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
last = here = ENTRY(header+1);
}
+ /* Iff we are modifying the block in-place, bh is locked here. */
+
if (not_found) {
/* Insert the new name. */
- int size = EXT3_XATTR_LEN(name_len);
- int rest = (char *)last - (char *)here;
+ size_t size = EXT3_XATTR_LEN(name_len);
+ size_t rest = (char *)last - (char *)here;
memmove((char *)here + size, here, rest);
memset(here, 0, size);
here->e_name_index = name_index;
here->e_name_len = name_len;
memcpy(here->e_name, name, name_len);
} else {
- /* Remove the old value. */
if (!here->e_value_block && here->e_value_size) {
char *first_val = (char *)header + min_offs;
- int offs = le16_to_cpu(here->e_value_offs);
+ size_t offs = le16_to_cpu(here->e_value_offs);
char *val = (char *)header + offs;
size_t size = EXT3_XATTR_SIZE(
le32_to_cpu(here->e_value_size));
+
+ if (size == EXT3_XATTR_SIZE(value_len)) {
+ /* The old and the new value have the same
+ size. Just replace. */
+ here->e_value_size = cpu_to_le32(value_len);
+ memset(val + size - EXT3_XATTR_PAD, 0,
+ EXT3_XATTR_PAD); /* Clear pad bytes. */
+ memcpy(val, value, value_len);
+ goto skip_replace;
+ }
+
+ /* Remove the old value. */
memmove(first_val + size, first_val, val - first_val);
memset(first_val, 0, size);
here->e_value_offs = 0;
@@ -662,7 +684,7 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
/* Adjust all value offsets. */
last = ENTRY(header+1);
while (!IS_LAST_ENTRY(last)) {
- int o = le16_to_cpu(last->e_value_offs);
+ size_t o = le16_to_cpu(last->e_value_offs);
if (!last->e_value_block && o < offs)
last->e_value_offs =
cpu_to_le16(o + size);
@@ -670,20 +692,12 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
}
}
if (value == NULL) {
- /* Remove this attribute. */
- if (EXT3_XATTR_NEXT(ENTRY(header+1)) == last) {
- /* This block is now empty. */
- error = ext3_xattr_set_handle2(handle, inode,
- bh, NULL);
- goto cleanup;
- } else {
- /* Remove the old name. */
- int size = EXT3_XATTR_LEN(name_len);
- last = ENTRY((char *)last - size);
- memmove(here, (char*)here + size,
- (char*)last - (char*)here);
- memset(last, 0, size);
- }
+ /* Remove the old name. */
+ size_t size = EXT3_XATTR_LEN(name_len);
+ last = ENTRY((char *)last - size);
+ memmove(here, (char*)here + size,
+ (char*)last - (char*)here);
+ memset(last, 0, size);
}
}
@@ -700,15 +714,25 @@ bad_block: ext3_error(sb, "ext3_xattr_set",
memcpy(val, value, value_len);
}
}
- ext3_xattr_rehash(header, here);
- error = ext3_xattr_set_handle2(handle, inode, bh, header);
+skip_replace:
+ if (IS_LAST_ENTRY(ENTRY(header+1))) {
+ /* This block is now empty. */
+ if (bh && header == HDR(bh))
+ unlock_buffer(bh); /* we were modifying in-place. */
+ error = ext3_xattr_set_handle2(handle, inode, bh, NULL);
+ } else {
+ ext3_xattr_rehash(header, here);
+ if (bh && header == HDR(bh))
+ unlock_buffer(bh); /* we were modifying in-place. */
+ error = ext3_xattr_set_handle2(handle, inode, bh, header);
+ }
cleanup:
brelse(bh);
if (!(bh && header == HDR(bh)))
kfree(header);
- up(&ext3_xattr_sem);
+ up_write(&EXT3_I(inode)->xattr_sem);
return error;
}
@@ -723,33 +747,34 @@ ext3_xattr_set_handle2(handle_t *handle, struct inode *inode,
{
struct super_block *sb = inode->i_sb;
struct buffer_head *new_bh = NULL;
- int error;
+ int credits = 0, error;
if (header) {
- new_bh = ext3_xattr_cache_find(inode, header);
+ new_bh = ext3_xattr_cache_find(handle, inode, header, &credits);
if (new_bh) {
/*
- * We found an identical block in the cache.
- * The old block will be released after updating
- * the inode.
+ * We found an identical block in the cache. The
+ * block returned is locked. The old block will
+ * be released after updating the inode.
*/
- ea_bdebug(new_bh, "%s block %ld",
+ ea_bdebug(new_bh, "%s block %lu",
(old_bh == new_bh) ? "keeping" : "reusing",
- new_bh->b_blocknr);
+ (unsigned long) new_bh->b_blocknr);
error = -EDQUOT;
- if (DQUOT_ALLOC_BLOCK(inode, 1))
- goto cleanup;
-
- error = ext3_journal_get_write_access(handle, new_bh);
- if (error)
+ if (DQUOT_ALLOC_BLOCK(inode, 1)) {
+ unlock_buffer(new_bh);
+ journal_release_buffer(handle, new_bh, credits);
goto cleanup;
+ }
HDR(new_bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(new_bh)->h_refcount) + 1);
ea_bdebug(new_bh, "refcount now=%d",
le32_to_cpu(HDR(new_bh)->h_refcount));
+ unlock_buffer(new_bh);
} else if (old_bh && header == HDR(old_bh)) {
- /* Keep this block. */
+ /* Keep this block. No need to lock the block as we
+ * don't need to change the reference count. */
new_bh = old_bh;
get_bh(new_bh);
ext3_xattr_cache_insert(new_bh);
@@ -759,7 +784,7 @@ ext3_xattr_set_handle2(handle_t *handle, struct inode *inode,
EXT3_SB(sb)->s_es->s_first_data_block) +
EXT3_I(inode)->i_block_group *
EXT3_BLOCKS_PER_GROUP(sb);
- int block = ext3_new_block(handle,
+ int block = ext3_new_block(handle,
inode, goal, 0, 0, &error);
if (error)
goto cleanup;
@@ -800,15 +825,14 @@ getblk_failed:
error = 0;
if (old_bh && old_bh != new_bh) {
/*
- * If there was an old block, and we are not still using it,
- * we now release the old block.
+ * If there was an old block, and we are no longer using it,
+ * release the old block.
*/
- unsigned int refcount = le32_to_cpu(HDR(old_bh)->h_refcount);
-
error = ext3_journal_get_write_access(handle, old_bh);
if (error)
goto cleanup;
- if (refcount == 1) {
+ lock_buffer(old_bh);
+ if (HDR(old_bh)->h_refcount == cpu_to_le32(1)) {
/* Free the old block. */
ea_bdebug(old_bh, "freeing");
ext3_free_blocks(handle, inode, old_bh->b_blocknr, 1);
@@ -820,12 +844,14 @@ getblk_failed:
ext3_forget(handle, 1, inode, old_bh,old_bh->b_blocknr);
} else {
/* Decrement the refcount only. */
- refcount--;
- HDR(old_bh)->h_refcount = cpu_to_le32(refcount);
+ HDR(old_bh)->h_refcount = cpu_to_le32(
+ le32_to_cpu(HDR(old_bh)->h_refcount) - 1);
DQUOT_FREE_BLOCK(inode, 1);
ext3_journal_dirty_metadata(handle, old_bh);
- ea_bdebug(old_bh, "refcount now=%d", refcount);
+ ea_bdebug(old_bh, "refcount now=%d",
+ le32_to_cpu(HDR(old_bh)->h_refcount));
}
+ unlock_buffer(old_bh);
}
cleanup:
@@ -869,12 +895,11 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
void
ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
{
- struct buffer_head *bh;
+ struct buffer_head *bh = NULL;
+ down_write(&EXT3_I(inode)->xattr_sem);
if (!EXT3_I(inode)->i_file_acl)
- return;
- down(&ext3_xattr_sem);
-
+ goto cleanup;
bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl);
if (!bh) {
ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
@@ -882,7 +907,6 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
EXT3_I(inode)->i_file_acl);
goto cleanup;
}
- ea_bdebug(bh, "b_count=%d", atomic_read(&(bh->b_count)));
if (HDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) ||
HDR(bh)->h_blocks != cpu_to_le32(1)) {
ext3_error(inode->i_sb, "ext3_xattr_delete_inode",
@@ -890,13 +914,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
EXT3_I(inode)->i_file_acl);
goto cleanup;
}
- ext3_journal_get_write_access(handle, bh);
- ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+ if (ext3_journal_get_write_access(handle, bh) != 0)
+ goto cleanup;
+ lock_buffer(bh);
if (HDR(bh)->h_refcount == cpu_to_le32(1)) {
ext3_xattr_cache_remove(bh);
ext3_free_blocks(handle, inode, EXT3_I(inode)->i_file_acl, 1);
+ get_bh(bh);
ext3_forget(handle, 1, inode, bh, EXT3_I(inode)->i_file_acl);
- bh = NULL;
} else {
HDR(bh)->h_refcount = cpu_to_le32(
le32_to_cpu(HDR(bh)->h_refcount) - 1);
@@ -905,11 +930,13 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode)
handle->h_sync = 1;
DQUOT_FREE_BLOCK(inode, 1);
}
+ ea_bdebug(bh, "refcount now=%d", le32_to_cpu(HDR(bh)->h_refcount) - 1);
+ unlock_buffer(bh);
EXT3_I(inode)->i_file_acl = 0;
cleanup:
brelse(bh);
- up(&ext3_xattr_sem);
+ up_write(&EXT3_I(inode)->xattr_sem);
}
/*
@@ -1005,7 +1032,8 @@ ext3_xattr_cmp(struct ext3_xattr_header *header1,
* not found or an error occurred.
*/
static struct buffer_head *
-ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
+ext3_xattr_cache_find(handle_t *handle, struct inode *inode,
+ struct ext3_xattr_header *header, int *credits)
{
__u32 hash = le32_to_cpu(header->h_hash);
struct mb_cache_entry *ce;
@@ -1013,7 +1041,8 @@ ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
if (!header->h_hash)
return NULL; /* never share */
ea_idebug(inode, "looking for cached blocks [%x]", (int)hash);
- ce = mb_cache_entry_find_first(ext3_xattr_cache, 0, inode->i_bdev, hash);
+ ce = mb_cache_entry_find_first(ext3_xattr_cache, 0,
+ inode->i_sb->s_bdev, hash);
while (ce) {
struct buffer_head *bh = sb_bread(inode->i_sb, ce->e_block);
@@ -1021,19 +1050,29 @@ ext3_xattr_cache_find(struct inode *inode, struct ext3_xattr_header *header)
ext3_error(inode->i_sb, "ext3_xattr_cache_find",
"inode %ld: block %ld read error",
inode->i_ino, (unsigned long) ce->e_block);
- } else if (le32_to_cpu(HDR(bh)->h_refcount) >
- EXT3_XATTR_REFCOUNT_MAX) {
- ea_idebug(inode, "block %ld refcount %d>%d",
- (unsigned long) ce->e_block,
- le32_to_cpu(HDR(bh)->h_refcount),
- EXT3_XATTR_REFCOUNT_MAX);
- } else if (!ext3_xattr_cmp(header, HDR(bh))) {
- ea_bdebug(bh, "b_count=%d",atomic_read(&(bh->b_count)));
- mb_cache_entry_release(ce);
- return bh;
+ } else {
+ /* ext3_journal_get_write_access() requires an unlocked
+ * bh, which complicates things here. */
+ if (ext3_journal_get_write_access_credits(handle, bh,
+ credits) != 0)
+ return NULL;
+ lock_buffer(bh);
+ if (le32_to_cpu(HDR(bh)->h_refcount) >
+ EXT3_XATTR_REFCOUNT_MAX) {
+ ea_idebug(inode, "block %ld refcount %d>%d",
+ (unsigned long) ce->e_block,
+ le32_to_cpu(HDR(bh)->h_refcount),
+ EXT3_XATTR_REFCOUNT_MAX);
+ } else if (!ext3_xattr_cmp(header, HDR(bh))) {
+ mb_cache_entry_release(ce);
+ /* buffer will be unlocked by caller */
+ return bh;
+ }
+ unlock_buffer(bh);
+ journal_release_buffer(handle, bh, *credits);
+ brelse(bh);
}
- brelse(bh);
- ce = mb_cache_entry_find_next(ce, 0, inode->i_bdev, hash);
+ ce = mb_cache_entry_find_next(ce, 0, inode->i_sb->s_bdev, hash);
}
return NULL;
}
diff --git a/fs/ext3/xattr_user.c b/fs/ext3/xattr_user.c
index b93a74ded763..84877afff67a 100644
--- a/fs/ext3/xattr_user.c
+++ b/fs/ext3/xattr_user.c
@@ -13,10 +13,6 @@
#include <linux/ext3_fs.h>
#include "xattr.h"
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
-# include "acl.h"
-#endif
-
#define XATTR_USER_PREFIX "user."
static size_t
@@ -46,11 +42,7 @@ ext3_xattr_user_get(struct inode *inode, const char *name,
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
- error = ext3_permission_locked(inode, MAY_READ);
-#else
- error = permission(inode, MAY_READ);
-#endif
+ error = permission(inode, MAY_READ, NULL);
if (error)
return error;
@@ -70,11 +62,7 @@ ext3_xattr_user_set(struct inode *inode, const char *name,
if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM;
-#ifdef CONFIG_EXT3_FS_POSIX_ACL
- error = ext3_permission_locked(inode, MAY_WRITE);
-#else
- error = permission(inode, MAY_WRITE);
-#endif
+ error = permission(inode, MAY_WRITE, NULL);
if (error)
return error;
diff --git a/fs/freevxfs/vxfs_lookup.c b/fs/freevxfs/vxfs_lookup.c
index 1f2c91676ee7..9c7f99f7bd01 100644
--- a/fs/freevxfs/vxfs_lookup.c
+++ b/fs/freevxfs/vxfs_lookup.c
@@ -51,7 +51,7 @@
#define VXFS_BLOCK_PER_PAGE(sbp) ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
-static struct dentry * vxfs_lookup(struct inode *, struct dentry *);
+static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int vxfs_readdir(struct file *, void *, filldir_t);
struct inode_operations vxfs_dir_inode_ops = {
@@ -193,6 +193,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
* vxfs_lookup - lookup pathname component
* @dip: dir in which we lookup
* @dp: dentry we lookup
+ * @nd: lookup nameidata
*
* Description:
* vxfs_lookup tries to lookup the pathname component described
@@ -203,7 +204,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
* in the return pointer.
*/
static struct dentry *
-vxfs_lookup(struct inode *dip, struct dentry *dp)
+vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
{
struct inode *ip = NULL;
ino_t ino;
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 92682b02ff12..8732f30faa2b 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -516,6 +516,7 @@ int generic_osync_inode(struct inode *inode, int what)
int need_write_inode_now = 0;
int err2;
+ current->flags |= PF_SYNCWRITE;
if (what & OSYNC_DATA)
err = filemap_fdatawrite(inode->i_mapping);
if (what & (OSYNC_METADATA|OSYNC_DATA)) {
@@ -528,6 +529,7 @@ int generic_osync_inode(struct inode *inode, int what)
if (!err)
err = err2;
}
+ current->flags &= ~PF_SYNCWRITE;
spin_lock(&inode_lock);
if ((inode->i_state & I_DIRTY) &&
diff --git a/fs/hfs/dir.c b/fs/hfs/dir.c
index fe696c097d27..40df8a2b116c 100644
--- a/fs/hfs/dir.c
+++ b/fs/hfs/dir.c
@@ -163,7 +163,7 @@ static inline void mark_inodes_deleted(struct hfs_cat_entry *entry,
* a directory and return a corresponding inode, given the inode for
* the directory and the name (and its length) of the new file.
*/
-int hfs_create(struct inode * dir, struct dentry *dentry, int mode)
+int hfs_create(struct inode * dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
struct hfs_cat_entry *entry = HFS_I(dir)->entry;
struct hfs_cat_entry *new;
diff --git a/fs/hfs/dir_cap.c b/fs/hfs/dir_cap.c
index 78da551630a4..62bbda0a6311 100644
--- a/fs/hfs/dir_cap.c
+++ b/fs/hfs/dir_cap.c
@@ -28,7 +28,7 @@
/*================ Forward declarations ================*/
-static struct dentry *cap_lookup(struct inode *, struct dentry *);
+static struct dentry *cap_lookup(struct inode *, struct dentry *, struct nameidata *);
static int cap_readdir(struct file *, void *, filldir_t);
/*================ Global variables ================*/
@@ -95,7 +95,7 @@ struct inode_operations hfs_cap_rdir_inode_operations = {
* inode corresponding to an entry in a directory, given the inode for
* the directory and the name (and its length) of the entry.
*/
-static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *cap_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
ino_t dtype;
struct hfs_name cname;
diff --git a/fs/hfs/dir_dbl.c b/fs/hfs/dir_dbl.c
index 36b7abd1eb6b..ee2ccef70fe7 100644
--- a/fs/hfs/dir_dbl.c
+++ b/fs/hfs/dir_dbl.c
@@ -24,9 +24,9 @@
/*================ Forward declarations ================*/
-static struct dentry *dbl_lookup(struct inode *, struct dentry *);
+static struct dentry *dbl_lookup(struct inode *, struct dentry *, struct nameidata *);
static int dbl_readdir(struct file *, void *, filldir_t);
-static int dbl_create(struct inode *, struct dentry *, int);
+static int dbl_create(struct inode *, struct dentry *, int, struct nameidata *);
static int dbl_mkdir(struct inode *, struct dentry *, int);
static int dbl_unlink(struct inode *, struct dentry *);
static int dbl_rmdir(struct inode *, struct dentry *);
@@ -108,7 +108,7 @@ static int is_hdr(struct inode *dir, const char *name, int len)
* the inode for the directory and the name (and its length) of the
* entry.
*/
-static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *dbl_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct hfs_name cname;
struct hfs_cat_entry *entry;
@@ -272,7 +272,7 @@ out:
* the directory and the name (and its length) of the new file.
*/
static int dbl_create(struct inode * dir, struct dentry *dentry,
- int mode)
+ int mode, struct nameidata *nd)
{
int error;
@@ -280,7 +280,7 @@ static int dbl_create(struct inode * dir, struct dentry *dentry,
if (is_hdr(dir, dentry->d_name.name, dentry->d_name.len)) {
error = -EEXIST;
} else {
- error = hfs_create(dir, dentry, mode);
+ error = hfs_create(dir, dentry, mode, nd);
}
unlock_kernel();
return error;
diff --git a/fs/hfs/dir_nat.c b/fs/hfs/dir_nat.c
index 5dda709ebdf5..9688bcf7c145 100644
--- a/fs/hfs/dir_nat.c
+++ b/fs/hfs/dir_nat.c
@@ -30,7 +30,7 @@
/*================ Forward declarations ================*/
-static struct dentry *nat_lookup(struct inode *, struct dentry *);
+static struct dentry *nat_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nat_readdir(struct file *, void *, filldir_t);
static int nat_rmdir(struct inode *, struct dentry *);
static int nat_hdr_unlink(struct inode *, struct dentry *);
@@ -97,7 +97,7 @@ struct inode_operations hfs_nat_hdir_inode_operations = {
* the inode corresponding to an entry in a directory, given the inode
* for the directory and the name (and its length) of the entry.
*/
-static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *nat_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
ino_t dtype;
struct hfs_name cname;
diff --git a/fs/hfs/sysdep.c b/fs/hfs/sysdep.c
index f0a08037ab1e..1b083b8b9a2f 100644
--- a/fs/hfs/sysdep.c
+++ b/fs/hfs/sysdep.c
@@ -19,7 +19,7 @@
#include <linux/hfs_fs.h>
#include <linux/smp_lock.h>
-static int hfs_revalidate_dentry(struct dentry *, int);
+static int hfs_revalidate_dentry(struct dentry *, struct nameidata *);
static int hfs_hash_dentry(struct dentry *, struct qstr *);
static int hfs_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
static void hfs_dentry_iput(struct dentry *, struct inode *);
@@ -90,7 +90,7 @@ static void hfs_dentry_iput(struct dentry *dentry, struct inode *inode)
iput(inode);
}
-static int hfs_revalidate_dentry(struct dentry *dentry, int flags)
+static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = dentry->d_inode;
int diff;
diff --git a/fs/hpfs/dir.c b/fs/hpfs/dir.c
index 1c1e10c72822..9f0a0d3b2382 100644
--- a/fs/hpfs/dir.c
+++ b/fs/hpfs/dir.c
@@ -198,7 +198,7 @@ out:
* to tell read_inode to read fnode or not.
*/
-struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
const char *name = dentry->d_name.name;
unsigned len = dentry->d_name.len;
diff --git a/fs/hpfs/hpfs_fn.h b/fs/hpfs/hpfs_fn.h
index 91f880e88362..a4dc5bab6efd 100644
--- a/fs/hpfs/hpfs_fn.h
+++ b/fs/hpfs/hpfs_fn.h
@@ -216,7 +216,7 @@ void hpfs_set_dentry_operations(struct dentry *);
int hpfs_dir_release(struct inode *, struct file *);
loff_t hpfs_dir_lseek(struct file *, loff_t, int);
int hpfs_readdir(struct file *, void *, filldir_t);
-struct dentry *hpfs_lookup(struct inode *, struct dentry *);
+struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
/* dnode.c */
@@ -285,7 +285,7 @@ void hpfs_decide_conv(struct inode *, unsigned char *, unsigned);
/* namei.c */
int hpfs_mkdir(struct inode *, struct dentry *, int);
-int hpfs_create(struct inode *, struct dentry *, int);
+int hpfs_create(struct inode *, struct dentry *, int, struct nameidata *);
int hpfs_mknod(struct inode *, struct dentry *, int, dev_t);
int hpfs_symlink(struct inode *, struct dentry *, const char *);
int hpfs_unlink(struct inode *, struct dentry *);
diff --git a/fs/hpfs/namei.c b/fs/hpfs/namei.c
index 8540f23659a0..866976557245 100644
--- a/fs/hpfs/namei.c
+++ b/fs/hpfs/namei.c
@@ -106,7 +106,7 @@ bail:
return -ENOSPC;
}
-int hpfs_create(struct inode *dir, struct dentry *dentry, int mode)
+int hpfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
const char *name = dentry->d_name.name;
unsigned len = dentry->d_name.len;
@@ -374,7 +374,7 @@ again:
d_drop(dentry);
spin_lock(&dentry->d_lock);
if (atomic_read(&dentry->d_count) > 1 ||
- permission(inode, MAY_WRITE) ||
+ permission(inode, MAY_WRITE, NULL) ||
get_write_access(inode)) {
spin_unlock(&dentry->d_lock);
d_rehash(dentry);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index f0d2a2c65170..5888e05f81bf 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -462,7 +462,7 @@ static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return retval;
}
-static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
}
diff --git a/fs/intermezzo/dcache.c b/fs/intermezzo/dcache.c
index 2d3ebd2a7611..91cd4d94b5e6 100644
--- a/fs/intermezzo/dcache.c
+++ b/fs/intermezzo/dcache.c
@@ -50,7 +50,7 @@
kmem_cache_t * presto_dentry_slab;
/* called when a cache lookup succeeds */
-static int presto_d_revalidate(struct dentry *de, int flag)
+static int presto_d_revalidate(struct dentry *de, struct nameidata *nd)
{
struct inode *inode = de->d_inode;
struct presto_file_set * root_fset;
diff --git a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c
index 0446fb4dc174..7e646f9c2211 100644
--- a/fs/intermezzo/dir.c
+++ b/fs/intermezzo/dir.c
@@ -81,7 +81,7 @@ static inline void presto_unlock(struct inode *dir)
/*
* these are initialized in super.c
*/
-extern int presto_permission(struct inode *inode, int mask);
+extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
static int izo_authorized_uid = 0;
int izo_dentry_is_ilookup(struct dentry *dentry, ino_t *id,
@@ -239,7 +239,7 @@ struct dentry *presto_add_ilookup_dentry(struct dentry *parent,
return de;
}
-struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
int rc = 0;
struct dentry *de;
@@ -286,7 +286,7 @@ struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry)
(dir, dentry, ino, generation);
is_ilookup = 1;
} else
- de = iops->lookup(dir, dentry);
+ de = iops->lookup(dir, dentry, nd);
#if 0
}
#endif
@@ -412,7 +412,8 @@ int presto_prep(struct dentry *dentry, struct presto_cache **cache,
return 0;
}
-static int presto_create(struct inode * dir, struct dentry * dentry, int mode)
+static int presto_create(struct inode * dir, struct dentry * dentry, int mode,
+ struct nameidata *nd)
{
int error;
struct presto_cache *cache;
@@ -829,7 +830,7 @@ int presto_rename(struct inode *old_dir, struct dentry *old_dentry,
* appropriate permission function. Thus we do not worry here about ACLs
* or EAs. -SHP
*/
-int presto_permission(struct inode *inode, int mask)
+int presto_permission(struct inode *inode, int mask, struct nameidata *nd)
{
unsigned short mode = inode->i_mode;
struct presto_cache *cache;
@@ -851,11 +852,11 @@ int presto_permission(struct inode *inode, int mask)
if ( S_ISREG(mode) && fiops && fiops->permission ) {
EXIT;
- return fiops->permission(inode, mask);
+ return fiops->permission(inode, mask, nd);
}
if ( S_ISDIR(mode) && diops && diops->permission ) {
EXIT;
- return diops->permission(inode, mask);
+ return diops->permission(inode, mask, nd);
}
}
@@ -866,7 +867,7 @@ int presto_permission(struct inode *inode, int mask)
* the VFS permission function.
*/
inode->i_op->permission = NULL;
- rc = permission(inode, mask);
+ rc = permission(inode, mask, nd);
inode->i_op->permission = &presto_permission;
EXIT;
diff --git a/fs/intermezzo/file.c b/fs/intermezzo/file.c
index 9f0b10422c4e..a1efcbfaa2c9 100644
--- a/fs/intermezzo/file.c
+++ b/fs/intermezzo/file.c
@@ -53,7 +53,7 @@
/*
* these are initialized in super.c
*/
-extern int presto_permission(struct inode *inode, int mask);
+extern int presto_permission(struct inode *inode, int mask, struct nameidata *nd);
static int presto_open_upcall(int minor, struct dentry *de)
diff --git a/fs/intermezzo/intermezzo_fs.h b/fs/intermezzo/intermezzo_fs.h
index 8d2d33fcee0e..3a7c60be8f26 100644
--- a/fs/intermezzo/intermezzo_fs.h
+++ b/fs/intermezzo/intermezzo_fs.h
@@ -370,7 +370,7 @@ extern int presto_ilookup_uid;
# define PRESTO_ILOOKUP_MAGIC "...ino:"
# define PRESTO_ILOOKUP_SEP ':'
int izo_dentry_is_ilookup(struct dentry *, ino_t *id, unsigned int *generation);
-struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry);
+struct dentry *presto_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd);
struct presto_dentry_data {
int dd_count; /* how mnay dentries are using this dentry */
diff --git a/fs/intermezzo/vfs.c b/fs/intermezzo/vfs.c
index 5dd78cfed581..1cfa4c9a4b60 100644
--- a/fs/intermezzo/vfs.c
+++ b/fs/intermezzo/vfs.c
@@ -134,7 +134,7 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
int error;
if (!victim->d_inode || victim->d_parent->d_inode != dir)
return -ENOENT;
- error = permission(dir,MAY_WRITE | MAY_EXEC);
+ error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
if (IS_APPEND(dir))
@@ -158,7 +158,7 @@ static inline int may_create(struct inode *dir, struct dentry *child) {
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
- return permission(dir,MAY_WRITE | MAY_EXEC);
+ return permission(dir,MAY_WRITE | MAY_EXEC, NULL);
}
#ifdef PRESTO_DEBUG
@@ -598,7 +598,7 @@ int presto_do_create(struct presto_file_set *fset, struct dentry *dir,
}
DQUOT_INIT(dir->d_inode);
lock_kernel();
- error = iops->create(dir->d_inode, dentry, mode);
+ error = iops->create(dir->d_inode, dentry, mode, NULL);
if (error) {
EXIT;
goto exit_lock;
@@ -1840,7 +1840,7 @@ int presto_rename_dir(struct presto_file_set *fset, struct dentry *old_parent,
* we'll need to flip '..'.
*/
if (new_dir != old_dir) {
- error = permission(old_dentry->d_inode, MAY_WRITE);
+ error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
}
if (error)
return error;
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 840cb90d4897..8d525f6bf606 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -158,7 +158,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
return 0;
}
-struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry)
+struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
unsigned long ino;
struct inode *inode;
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
index 54f7862a3717..2580162cad52 100644
--- a/fs/jbd/commit.c
+++ b/fs/jbd/commit.c
@@ -169,10 +169,23 @@ void journal_commit_transaction(journal_t *journal)
* that multiple journal_get_write_access() calls to the same
* buffer are perfectly permissable.
*/
- while (commit_transaction->t_reserved_list) {
- jh = commit_transaction->t_reserved_list;
- JBUFFER_TRACE(jh, "reserved, unused: refile");
- journal_refile_buffer(journal, jh);
+ {
+ int nr = 0;
+ while (commit_transaction->t_reserved_list) {
+ jh = commit_transaction->t_reserved_list;
+ JBUFFER_TRACE(jh, "reserved, unused: refile");
+ journal_refile_buffer(journal, jh);
+ nr++;
+ }
+ if (nr) {
+ static int noisy;
+
+ if (noisy < 10) {
+ noisy++;
+ printk("%s: freed %d reserved buffers\n",
+ __FUNCTION__, nr);
+ }
+ }
}
/*
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c
index 54e16b97fdaa..12ad174e7662 100644
--- a/fs/jbd/transaction.c
+++ b/fs/jbd/transaction.c
@@ -1168,37 +1168,24 @@ out:
* journal_release_buffer: undo a get_write_access without any buffer
* updates, if the update decided in the end that it didn't need access.
*
- * journal_get_write_access() can block, so it is quite possible for a
- * journaling component to decide after the write access is returned
- * that global state has changed and the update is no longer required.
- *
* The caller passes in the number of credits which should be put back for
* this buffer (zero or one).
+ *
+ * We leave the buffer attached to t_reserved_list because even though this
+ * handle doesn't want it, some other concurrent handle may want to journal
+ * this buffer. If that handle is curently in between get_write_access() and
+ * journal_dirty_metadata() then it expects the buffer to be reserved. If
+ * we were to rip it off t_reserved_list here, the other handle will explode
+ * when journal_dirty_metadata is presented with a non-reserved buffer.
+ *
+ * If nobody really wants to journal this buffer then it will be thrown
+ * away at the start of commit.
*/
void
journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
{
- transaction_t *transaction = handle->h_transaction;
- journal_t *journal = transaction->t_journal;
- struct journal_head *jh = bh2jh(bh);
-
- JBUFFER_TRACE(jh, "entry");
-
- /* If the buffer is reserved but not modified by this
- * transaction, then it is safe to release it. In all other
- * cases, just leave the buffer as it is. */
-
- jbd_lock_bh_state(bh);
- spin_lock(&journal->j_list_lock);
- if (jh->b_jlist == BJ_Reserved && jh->b_transaction == transaction &&
- !buffer_jbddirty(jh2bh(jh))) {
- JBUFFER_TRACE(jh, "unused: refiling it");
- __journal_refile_buffer(jh);
- }
- spin_unlock(&journal->j_list_lock);
- jbd_unlock_bh_state(bh);
+ BUFFER_TRACE(bh, "entry");
handle->h_buffer_credits += credits;
- JBUFFER_TRACE(jh, "exit");
}
/**
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
index e7e6d5442774..94d3560caeae 100644
--- a/fs/jffs/inode-v23.c
+++ b/fs/jffs/inode-v23.c
@@ -642,7 +642,7 @@ jffs_readdir(struct file *filp, void *dirent, filldir_t filldir)
/* Find a file in a directory. If the file exists, return its
corresponding dentry. */
static struct dentry *
-jffs_lookup(struct inode *dir, struct dentry *dentry)
+jffs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct jffs_file *d;
struct jffs_file *f;
@@ -1273,7 +1273,8 @@ jffs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
* with d_instantiate().
*/
static int
-jffs_create(struct inode *dir, struct dentry *dentry, int mode)
+jffs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct jffs_raw_inode raw_inode;
struct jffs_control *c;
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index 61d1b71bc20c..9a2df58cb486 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -32,8 +32,8 @@ typedef dev_t mknod_arg_t;
static int jffs2_readdir (struct file *, void *, filldir_t);
-static int jffs2_create (struct inode *,struct dentry *,int);
-static struct dentry *jffs2_lookup (struct inode *,struct dentry *);
+static int jffs2_create (struct inode *,struct dentry *,int, struct nameidata *);
+static struct dentry *jffs2_lookup (struct inode *,struct dentry *, struct nameidata *);
static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
static int jffs2_unlink (struct inode *,struct dentry *);
static int jffs2_symlink (struct inode *,struct dentry *,const char *);
@@ -73,7 +73,7 @@ struct inode_operations jffs2_dir_inode_operations =
and we use the same hash function as the dentries. Makes this
nice and simple
*/
-static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target)
+static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, struct nameidata *nd)
{
struct jffs2_inode_info *dir_f;
struct jffs2_sb_info *c;
@@ -175,7 +175,8 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
/***********************************************************************/
-static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode)
+static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct jffs2_raw_inode *ri;
struct jffs2_inode_info *f, *dir_f;
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 758d370e6419..a83ab660a0b7 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -208,7 +208,7 @@ check_capabilities:
return -EACCES;
}
-int jfs_permission(struct inode * inode, int mask)
+int jfs_permission(struct inode * inode, int mask, struct nameidata *nd)
{
return __jfs_permission(inode, mask, 0);
}
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index 179a3893a945..cfb445231972 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -25,7 +25,7 @@
struct posix_acl *jfs_get_acl(struct inode *, int);
int jfs_set_acl(struct inode *, int, struct posix_acl *);
int jfs_permission_have_sem(struct inode *, int);
-int jfs_permission(struct inode *, int);
+int jfs_permission(struct inode *, int, struct nameidata *);
int jfs_init_acl(struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index fd1467521794..3bf710dd0901 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -54,11 +54,13 @@ s64 commitZeroLink(tid_t, struct inode *);
* PARAMETER: dip - parent directory vnode
* dentry - dentry of new file
* mode - create mode (rwxrwxrwx).
+ * nd- nd struct
*
* RETURN: Errors from subroutines
*
*/
-int jfs_create(struct inode *dip, struct dentry *dentry, int mode)
+int jfs_create(struct inode *dip, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
int rc = 0;
tid_t tid; /* transaction id */
@@ -1373,7 +1375,7 @@ int jfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
return -rc;
}
-static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry)
+static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
{
struct btstack btstack;
ino_t inum;
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index a9c455de618b..79126b49c813 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -731,7 +731,7 @@ static int can_set_xattr(struct inode *inode, const char *name,
#ifdef CONFIG_JFS_POSIX_ACL
return jfs_permission_have_sem(inode, MAY_WRITE);
#else
- return permission(inode, MAY_WRITE);
+ return permission(inode, MAY_WRITE, NULL);
#endif
}
@@ -893,7 +893,7 @@ static int can_get_xattr(struct inode *inode, const char *name)
else
return jfs_permission_have_sem(inode, MAY_READ);
#else
- return permission(inode, MAY_READ);
+ return permission(inode, MAY_READ, NULL);
#endif
}
@@ -964,10 +964,17 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
ssize_t jfs_getxattr(struct dentry *dentry, const char *name, void *data,
size_t buf_size)
{
- return __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+ int err;
+
+ down(&dentry->d_inode->i_sem);
+ err = __jfs_getxattr(dentry->d_inode, name, data, buf_size);
+ up(&dentry->d_inode->i_sem);
+
+ return err;
}
-ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+static ssize_t __jfs_listxattr(struct dentry * dentry, char *data,
+ size_t buf_size)
{
struct inode *inode = dentry->d_inode;
char *buffer;
@@ -1013,6 +1020,17 @@ ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
return size;
}
+ssize_t jfs_listxattr(struct dentry * dentry, char *data, size_t buf_size)
+{
+ int err;
+
+ down(&dentry->d_inode->i_sem);
+ err = __jfs_listxattr(dentry, data, buf_size);
+ up(&dentry->d_inode->i_sem);
+
+ return err;
+}
+
int jfs_removexattr(struct dentry *dentry, const char *name)
{
return __jfs_setxattr(dentry->d_inode, name, 0, 0, XATTR_REPLACE);
diff --git a/fs/libfs.c b/fs/libfs.c
index 62fb3c0fbc24..884da83cf77a 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -29,7 +29,7 @@ int simple_statfs(struct super_block *sb, struct kstatfs *buf)
* exist, we know it is negative.
*/
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
d_add(dentry, NULL);
return NULL;
diff --git a/fs/minix/namei.c b/fs/minix/namei.c
index d2b9ae264ce1..2b9e6c64d25a 100644
--- a/fs/minix/namei.c
+++ b/fs/minix/namei.c
@@ -54,7 +54,7 @@ struct dentry_operations minix_dentry_operations = {
.d_hash = minix_hash,
};
-static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode = NULL;
ino_t ino;
@@ -89,7 +89,8 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, int mode, dev_
return error;
}
-static int minix_create(struct inode * dir, struct dentry *dentry, int mode)
+static int minix_create(struct inode * dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
return minix_mknod(dir, dentry, mode, 0);
}
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c
index 31eb0d076c1f..19c047776ecd 100644
--- a/fs/msdos/namei.c
+++ b/fs/msdos/namei.c
@@ -193,7 +193,7 @@ static struct dentry_operations msdos_dentry_operations = {
*/
/***** Get inode using directory and name */
-struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry)
+struct dentry *msdos_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
@@ -261,7 +261,8 @@ static int msdos_add_entry(struct inode *dir, const char *name,
*/
/***** Create a file */
-int msdos_create(struct inode *dir,struct dentry *dentry,int mode)
+int msdos_create(struct inode *dir,struct dentry *dentry,int mode,
+ struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct buffer_head *bh;
diff --git a/fs/namei.c b/fs/namei.c
index 8c847a1963f8..4bd15bdcef47 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -203,7 +203,7 @@ int vfs_permission(struct inode * inode, int mask)
return -EACCES;
}
-int permission(struct inode * inode,int mask)
+int permission(struct inode * inode,int mask, struct nameidata *nd)
{
int retval;
int submask;
@@ -212,7 +212,7 @@ int permission(struct inode * inode,int mask)
submask = mask & ~MAY_APPEND;
if (inode->i_op && inode->i_op->permission)
- retval = inode->i_op->permission(inode, submask);
+ retval = inode->i_op->permission(inode, submask, nd);
else
retval = vfs_permission(inode, submask);
if (retval)
@@ -273,7 +273,7 @@ void path_release(struct nameidata *nd)
* Internal lookup() using the new generic dcache.
* SMP-safe
*/
-static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * dentry = __d_lookup(parent, name);
@@ -284,7 +284,7 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
dentry = d_lookup(parent, name);
if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {
- if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {
+ if (!dentry->d_op->d_revalidate(dentry, nd) && !d_invalidate(dentry)) {
dput(dentry);
dentry = NULL;
}
@@ -336,7 +336,7 @@ ok:
* make sure that nobody added the entry to the dcache in the meantime..
* SMP-safe
*/
-static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)
+static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, struct nameidata *nd)
{
struct dentry * result;
struct inode *dir = parent->d_inode;
@@ -361,7 +361,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i
struct dentry * dentry = d_alloc(parent, name);
result = ERR_PTR(-ENOMEM);
if (dentry) {
- result = dir->i_op->lookup(dir, dentry);
+ result = dir->i_op->lookup(dir, dentry, nd);
if (result)
dput(dentry);
else
@@ -377,7 +377,7 @@ static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, i
*/
up(&dir->i_sem);
if (result->d_op && result->d_op->d_revalidate) {
- if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {
+ if (!result->d_op->d_revalidate(result, nd) && !d_invalidate(result)) {
dput(result);
result = ERR_PTR(-ENOENT);
}
@@ -524,7 +524,7 @@ struct path {
* It _is_ time-critical.
*/
static int do_lookup(struct nameidata *nd, struct qstr *name,
- struct path *path, int flags)
+ struct path *path)
{
struct vfsmount *mnt = nd->mnt;
struct dentry *dentry = __d_lookup(nd->dentry, name);
@@ -539,13 +539,13 @@ done:
return 0;
need_lookup:
- dentry = real_lookup(nd->dentry, name, LOOKUP_CONTINUE);
+ dentry = real_lookup(nd->dentry, name, nd);
if (IS_ERR(dentry))
goto fail;
goto done;
need_revalidate:
- if (dentry->d_op->d_revalidate(dentry, flags))
+ if (dentry->d_op->d_revalidate(dentry, nd))
goto done;
if (d_invalidate(dentry))
goto done;
@@ -588,7 +588,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
err = exec_permission_lite(inode);
if (err == -EAGAIN) {
- err = permission(inode, MAY_EXEC);
+ err = permission(inode, MAY_EXEC, nd);
}
if (err)
break;
@@ -638,8 +638,9 @@ int link_path_walk(const char * name, struct nameidata *nd)
if (err < 0)
break;
}
+ nd->flags |= LOOKUP_CONTINUE;
/* This does the actual lookups.. */
- err = do_lookup(nd, &this, &next, LOOKUP_CONTINUE);
+ err = do_lookup(nd, &this, &next);
if (err)
break;
/* Check mountpoints.. */
@@ -681,6 +682,7 @@ int link_path_walk(const char * name, struct nameidata *nd)
last_with_slashes:
lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
last_component:
+ nd->flags &= ~LOOKUP_CONTINUE;
if (lookup_flags & LOOKUP_PARENT)
goto lookup_parent;
if (this.name[0] == '.') switch (this.len) {
@@ -700,7 +702,7 @@ last_component:
if (err < 0)
break;
}
- err = do_lookup(nd, &this, &next, 0);
+ err = do_lookup(nd, &this, &next);
if (err)
break;
follow_mount(&next.mnt, &next.dentry);
@@ -769,6 +771,7 @@ static int __emul_lookup_dentry(const char *name, struct nameidata *nd)
*/
nd_root.last_type = LAST_ROOT;
nd_root.flags = nd->flags;
+ memcpy(&nd_root.intent, &nd->intent, sizeof(nd_root.intent));
read_lock(&current->fs->lock);
nd_root.mnt = mntget(current->fs->rootmnt);
nd_root.dentry = dget(current->fs->root);
@@ -866,14 +869,14 @@ int path_lookup(const char *name, unsigned int flags, struct nameidata *nd)
* needs parent already locked. Doesn't follow mounts.
* SMP-safe.
*/
-struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+static struct dentry * __lookup_hash(struct qstr *name, struct dentry * base, struct nameidata *nd)
{
struct dentry * dentry;
struct inode *inode;
int err;
inode = base->d_inode;
- err = permission(inode, MAY_EXEC);
+ err = permission(inode, MAY_EXEC, nd);
dentry = ERR_PTR(err);
if (err)
goto out;
@@ -889,13 +892,13 @@ struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
goto out;
}
- dentry = cached_lookup(base, name, 0);
+ dentry = cached_lookup(base, name, nd);
if (!dentry) {
struct dentry *new = d_alloc(base, name);
dentry = ERR_PTR(-ENOMEM);
if (!new)
goto out;
- dentry = inode->i_op->lookup(inode, new);
+ dentry = inode->i_op->lookup(inode, new, nd);
if (!dentry)
dentry = new;
else
@@ -905,6 +908,11 @@ out:
return dentry;
}
+struct dentry * lookup_hash(struct qstr *name, struct dentry * base)
+{
+ return __lookup_hash(name, base, NULL);
+}
+
/* SMP-safe */
struct dentry * lookup_one_len(const char * name, struct dentry * base, int len)
{
@@ -988,12 +996,12 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
-static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
+static inline int may_delete(struct inode *dir,struct dentry *victim,int isdir)
{
int error;
if (!victim->d_inode || victim->d_parent->d_inode != dir)
return -ENOENT;
- error = permission(dir,MAY_WRITE | MAY_EXEC);
+ error = permission(dir,MAY_WRITE | MAY_EXEC, NULL);
if (error)
return error;
if (IS_APPEND(dir))
@@ -1023,12 +1031,14 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
* 3. We should have write and exec permissions on dir
* 4. We can't do it if dir is immutable (done in permission())
*/
-static inline int may_create(struct inode *dir, struct dentry *child) {
+static inline int may_create(struct inode *dir, struct dentry *child,
+ struct nameidata *nd)
+{
if (child->d_inode)
return -EEXIST;
if (IS_DEADDIR(dir))
return -ENOENT;
- return permission(dir,MAY_WRITE | MAY_EXEC);
+ return permission(dir,MAY_WRITE | MAY_EXEC, nd);
}
/*
@@ -1097,9 +1107,10 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
}
}
-int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
+int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, nd);
if (error)
return error;
@@ -1112,7 +1123,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode)
if (error)
return error;
DQUOT_INIT(dir);
- error = dir->i_op->create(dir, dentry, mode);
+ error = dir->i_op->create(dir, dentry, mode, nd);
if (!error) {
inode_dir_notify(dir, DN_CREATE);
security_inode_post_create(dir, dentry, mode);
@@ -1135,7 +1146,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR;
- error = permission(inode, acc_mode);
+ error = permission(inode, acc_mode, nd);
if (error)
return error;
@@ -1222,11 +1233,15 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
if (flag & O_APPEND)
acc_mode |= MAY_APPEND;
+ /* Fill in the open() intent data */
+ nd->intent.open.flags = flag;
+ nd->intent.open.create_mode = mode;
+
/*
* The simplest case - just a plain lookup.
*/
if (!(flag & O_CREAT)) {
- error = path_lookup(pathname, lookup_flags(flag), nd);
+ error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd);
if (error)
return error;
dentry = nd->dentry;
@@ -1236,7 +1251,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
/*
* Create - we need to know the parent.
*/
- error = path_lookup(pathname, LOOKUP_PARENT, nd);
+ error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd);
if (error)
return error;
@@ -1250,8 +1265,9 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
goto exit;
dir = nd->dentry;
+ nd->flags &= ~LOOKUP_PARENT;
down(&dir->d_inode->i_sem);
- dentry = lookup_hash(&nd->last, nd->dentry);
+ dentry = __lookup_hash(&nd->last, nd->dentry, nd);
do_last:
error = PTR_ERR(dentry);
@@ -1264,7 +1280,7 @@ do_last:
if (!dentry->d_inode) {
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, dentry, mode);
+ error = vfs_create(dir->d_inode, dentry, mode, nd);
up(&dir->d_inode->i_sem);
dput(nd->dentry);
nd->dentry = dentry;
@@ -1328,6 +1344,7 @@ do_link:
* stored in nd->last.name and we will have to putname() it when we
* are done. Procfs-like symlinks just set LAST_BIND.
*/
+ nd->flags |= LOOKUP_PARENT;
error = security_inode_follow_link(dentry, nd);
if (error)
goto exit_dput;
@@ -1336,6 +1353,7 @@ do_link:
dput(dentry);
if (error)
return error;
+ nd->flags &= ~LOOKUP_PARENT;
if (nd->last_type == LAST_BIND) {
dentry = nd->dentry;
goto ok;
@@ -1354,7 +1372,7 @@ do_link:
}
dir = nd->dentry;
down(&dir->d_inode->i_sem);
- dentry = lookup_hash(&nd->last, nd->dentry);
+ dentry = __lookup_hash(&nd->last, nd->dentry, nd);
putname(nd->last.name);
goto do_last;
}
@@ -1368,6 +1386,7 @@ static struct dentry *lookup_create(struct nameidata *nd, int is_dir)
dentry = ERR_PTR(-EEXIST);
if (nd->last_type != LAST_NORM)
goto fail;
+ nd->flags &= ~LOOKUP_PARENT;
dentry = lookup_hash(&nd->last, nd->dentry);
if (IS_ERR(dentry))
goto fail;
@@ -1383,7 +1402,7 @@ fail:
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1431,7 +1450,7 @@ asmlinkage long sys_mknod(const char __user * filename, int mode, dev_t dev)
if (!IS_ERR(dentry)) {
switch (mode & S_IFMT) {
case 0: case S_IFREG:
- error = vfs_create(nd.dentry->d_inode,dentry,mode);
+ error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
break;
case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:
error = vfs_mknod(nd.dentry->d_inode,dentry,mode,dev);
@@ -1454,7 +1473,7 @@ out:
int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1700,7 +1719,7 @@ slashes:
int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
- int error = may_create(dir, dentry);
+ int error = may_create(dir, dentry, NULL);
if (error)
return error;
@@ -1762,7 +1781,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de
if (!inode)
return -ENOENT;
- error = may_create(dir, new_dentry);
+ error = may_create(dir, new_dentry, NULL);
if (error)
return error;
@@ -1883,7 +1902,7 @@ int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
* we'll need to flip '..'.
*/
if (new_dir != old_dir) {
- error = permission(old_dentry->d_inode, MAY_WRITE);
+ error = permission(old_dentry->d_inode, MAY_WRITE, NULL);
if (error)
return error;
}
@@ -1961,7 +1980,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
return error;
if (!new_dentry->d_inode)
- error = may_create(new_dir, new_dentry);
+ error = may_create(new_dir, new_dentry, NULL);
else
error = may_delete(new_dir, new_dentry, is_dir);
if (error)
diff --git a/fs/namespace.c b/fs/namespace.c
index 61e5ec891363..a31cd95801cb 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -403,7 +403,7 @@ static int mount_is_safe(struct nameidata *nd)
if (current->uid != nd->dentry->d_inode->i_uid)
return -EPERM;
}
- if (permission(nd->dentry->d_inode, MAY_WRITE))
+ if (permission(nd->dentry->d_inode, MAY_WRITE, nd))
return -EPERM;
return 0;
#endif
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index d4577dc7a551..f10460e559a5 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -34,8 +34,8 @@ static void ncp_do_readdir(struct file *, void *, filldir_t,
static int ncp_readdir(struct file *, void *, filldir_t);
-static int ncp_create(struct inode *, struct dentry *, int);
-static struct dentry *ncp_lookup(struct inode *, struct dentry *);
+static int ncp_create(struct inode *, struct dentry *, int, struct nameidata *);
+static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
static int ncp_unlink(struct inode *, struct dentry *);
static int ncp_mkdir(struct inode *, struct dentry *, int);
static int ncp_rmdir(struct inode *, struct dentry *);
@@ -72,7 +72,7 @@ struct inode_operations ncp_dir_inode_operations =
/*
* Dentry operations routines
*/
-static int ncp_lookup_validate(struct dentry *, int);
+static int ncp_lookup_validate(struct dentry *, struct nameidata *);
static int ncp_hash_dentry(struct dentry *, struct qstr *);
static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
static int ncp_delete_dentry(struct dentry *);
@@ -264,7 +264,7 @@ leave_me:;
static int
-__ncp_lookup_validate(struct dentry * dentry, int flags)
+__ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
{
struct ncp_server *server;
struct dentry *parent;
@@ -333,11 +333,11 @@ finished:
}
static int
-ncp_lookup_validate(struct dentry * dentry, int flags)
+ncp_lookup_validate(struct dentry * dentry, struct nameidata *nd)
{
int res;
lock_kernel();
- res = __ncp_lookup_validate(dentry, flags);
+ res = __ncp_lookup_validate(dentry, nd);
unlock_kernel();
return res;
}
@@ -797,7 +797,7 @@ out:
return result;
}
-static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry)
+static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct ncp_server *server = NCP_SERVER(dir);
struct inode *inode = NULL;
@@ -942,7 +942,8 @@ out:
return error;
}
-static int ncp_create(struct inode *dir, struct dentry *dentry, int mode)
+static int ncp_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
return ncp_create_new(dir, dentry, mode, 0, 0);
}
diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c
index 3497f67be924..fb3e550a9abc 100644
--- a/fs/ncpfs/ioctl.c
+++ b/fs/ncpfs/ioctl.c
@@ -40,7 +40,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
switch (cmd) {
case NCP_IOC_NCPREQUEST:
- if ((permission(inode, MAY_WRITE) != 0)
+ if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) {
return -EACCES;
}
@@ -99,7 +99,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
struct ncp_fs_info info;
- if ((permission(inode, MAY_WRITE) != 0)
+ if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) {
return -EACCES;
}
@@ -127,7 +127,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
struct ncp_fs_info_v2 info2;
- if ((permission(inode, MAY_WRITE) != 0)
+ if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) {
return -EACCES;
}
@@ -155,7 +155,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
unsigned long tmp = server->m.mounted_uid;
- if ( (permission(inode, MAY_READ) != 0)
+ if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -169,7 +169,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
struct ncp_setroot_ioctl sr;
- if ( (permission(inode, MAY_READ) != 0)
+ if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -249,7 +249,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_PACKET_SIGNING
case NCP_IOC_SIGN_INIT:
- if ((permission(inode, MAY_WRITE) != 0)
+ if ((permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -272,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
return 0;
case NCP_IOC_SIGN_WANTED:
- if ( (permission(inode, MAY_READ) != 0)
+ if ( (permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -285,7 +285,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
{
int newstate;
- if ( (permission(inode, MAY_WRITE) != 0)
+ if ( (permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -306,7 +306,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp,
#ifdef CONFIG_NCPFS_IOCTL_LOCKING
case NCP_IOC_LOCKUNLOCK:
- if ( (permission(inode, MAY_WRITE) != 0)
+ if ( (permission(inode, MAY_WRITE, NULL) != 0)
&& (current->uid != server->m.mounted_uid))
{
return -EACCES;
@@ -608,7 +608,7 @@ outrel:
}
#endif /* CONFIG_NCPFS_NLS */
case NCP_IOC_SETDENTRYTTL:
- if ((permission(inode, MAY_WRITE) != 0) &&
+ if ((permission(inode, MAY_WRITE, NULL) != 0) &&
(current->uid != server->m.mounted_uid))
return -EACCES;
{
@@ -637,7 +637,7 @@ outrel:
/* NCP_IOC_GETMOUNTUID may be same as NCP_IOC_GETMOUNTUID2,
so we have this out of switch */
if (cmd == NCP_IOC_GETMOUNTUID) {
- if ((permission(inode, MAY_READ) != 0)
+ if ((permission(inode, MAY_READ, NULL) != 0)
&& (current->uid != server->m.mounted_uid)) {
return -EACCES;
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index d5499baadd1c..fd894fa6584b 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -37,10 +37,10 @@
static int nfs_opendir(struct inode *, struct file *);
static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *);
+static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
static int nfs_cached_lookup(struct inode *, struct dentry *,
struct nfs_fh *, struct nfs_fattr *);
-static int nfs_create(struct inode *, struct dentry *, int);
+static int nfs_create(struct inode *, struct dentry *, int, struct nameidata *);
static int nfs_mkdir(struct inode *, struct dentry *, int);
static int nfs_rmdir(struct inode *, struct dentry *);
static int nfs_unlink(struct inode *, struct dentry *);
@@ -78,13 +78,9 @@ struct inode_operations nfs_dir_inode_operations = {
static int
nfs_opendir(struct inode *inode, struct file *filp)
{
- struct nfs_server *server = NFS_SERVER(inode);
int res = 0;
lock_kernel();
- /* Do cto revalidation */
- if (!(server->flags & NFS_MOUNT_NOCTO))
- res = __nfs_revalidate_inode(server, inode);
/* Call generic open code in order to cache credentials */
if (!res)
res = nfs_open(inode, filp);
@@ -485,9 +481,13 @@ static inline void nfs_renew_times(struct dentry * dentry)
}
static inline
-int nfs_lookup_verify_inode(struct inode *inode)
+int nfs_lookup_verify_inode(struct inode *inode, int isopen)
{
- return nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ struct nfs_server *server = NFS_SERVER(inode);
+
+ if (isopen && !(server->flags & NFS_MOUNT_NOCTO))
+ return __nfs_revalidate_inode(server, inode);
+ return nfs_revalidate_inode(server, inode);
}
/*
@@ -497,8 +497,17 @@ int nfs_lookup_verify_inode(struct inode *inode)
* If parent mtime has changed, we revalidate, else we wait for a
* period corresponding to the parent's attribute cache timeout value.
*/
-static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
+static inline
+int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
{
+ int ndflags = 0;
+
+ if (nd)
+ ndflags = nd->flags;
+ /* Don't revalidate a negative dentry if we're creating a new file */
+ if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
+ return 0;
if (!nfs_check_verifier(dir, dentry))
return 1;
return time_after(jiffies, dentry->d_time + NFS_ATTRTIMEO(dir));
@@ -515,7 +524,7 @@ static inline int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry)
* If the parent directory is seen to have changed, we throw out the
* cached dentry and do a new lookup.
*/
-static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
+static int nfs_lookup_revalidate(struct dentry * dentry, struct nameidata *nd)
{
struct inode *dir;
struct inode *inode;
@@ -523,14 +532,18 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
+ int isopen = 0;
parent = dget_parent(dentry);
lock_kernel();
dir = parent->d_inode;
inode = dentry->d_inode;
+ if (nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_OPEN))
+ isopen = 1;
+
if (!inode) {
- if (nfs_neg_need_reval(dir, dentry))
+ if (nfs_neg_need_reval(dir, dentry, nd))
goto out_bad;
goto out_valid;
}
@@ -543,7 +556,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
/* Force a full look up iff the parent directory has changed */
if (nfs_check_verifier(dir, dentry)) {
- if (nfs_lookup_verify_inode(inode))
+ if (nfs_lookup_verify_inode(inode, isopen))
goto out_bad;
goto out_valid;
}
@@ -552,7 +565,7 @@ static int nfs_lookup_revalidate(struct dentry * dentry, int flags)
if (!error) {
if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
goto out_bad;
- if (nfs_lookup_verify_inode(inode))
+ if (nfs_lookup_verify_inode(inode, isopen))
goto out_bad;
goto out_valid_renew;
}
@@ -630,7 +643,17 @@ struct dentry_operations nfs_dentry_operations = {
.d_iput = nfs_dentry_iput,
};
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
+static inline
+int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
+{
+ if (NFS_PROTO(dir)->version == 2)
+ return 0;
+ if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+ return 0;
+ return (nd->intent.open.flags & O_EXCL) != 0;
+}
+
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
int error;
@@ -647,6 +670,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
error = -ENOMEM;
dentry->d_op = &nfs_dentry_operations;
+ /* If we're doing an exclusive create, optimize away the lookup */
+ if (nfs_is_exclusive_create(dir, nd))
+ return NULL;
+
lock_kernel();
error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
if (!error) {
@@ -787,12 +814,14 @@ out_err:
* that the operation succeeded on the server, but an error in the
* reply path made it appear to have failed.
*/
-static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct iattr attr;
struct nfs_fattr fattr;
struct nfs_fh fhandle;
int error;
+ int open_flags = 0;
dfprintk(VFS, "NFS: create(%s/%ld, %s\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name);
@@ -800,6 +829,9 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
attr.ia_mode = mode;
attr.ia_valid = ATTR_MODE;
+ if (nd && (nd->flags & LOOKUP_CREATE))
+ open_flags = nd->intent.open.flags;
+
/*
* The 0 argument passed into the create function should one day
* contain the O_EXCL flag if requested. This allows NFSv3 to
@@ -809,7 +841,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode)
lock_kernel();
nfs_zap_caches(dir);
error = NFS_PROTO(dir)->create(dir, &dentry->d_name,
- &attr, 0, &fhandle, &fattr);
+ &attr, open_flags, &fhandle, &fattr);
if (!error)
error = nfs_instantiate(dentry, &fhandle, &fattr);
else
@@ -1239,13 +1271,20 @@ out:
}
int
-nfs_permission(struct inode *inode, int mask)
+nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct nfs_access_cache *cache = &NFS_I(inode)->cache_access;
struct rpc_cred *cred;
int mode = inode->i_mode;
int res;
+ /* Are we checking permissions on anything other than lookup? */
+ if (!(mask & MAY_EXEC)) {
+ /* We only need to check permissions on file open() and access() */
+ if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
+ return 0;
+ }
+
if (mask & MAY_WRITE) {
/*
*
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 26956c7de1d8..7375f369e517 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -82,9 +82,6 @@ nfs_file_open(struct inode *inode, struct file *filp)
/* Do NFSv4 open() call */
if ((open = server->rpc_ops->file_open) != NULL)
res = open(inode, filp);
- /* Do cto revalidation */
- else if (!(server->flags & NFS_MOUNT_NOCTO))
- res = __nfs_revalidate_inode(server, inode);
/* Call generic open code in order to cache credentials */
if (!res)
res = nfs_open(inode, filp);
@@ -104,11 +101,13 @@ nfs_file_flush(struct file *file)
dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);
+ lock_kernel();
status = nfs_wb_file(inode, file);
if (!status) {
status = file->f_error;
file->f_error = 0;
}
+ unlock_kernel();
return status;
}
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 6d023b27ff6b..32a50f1bed11 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -56,7 +56,7 @@ int nfsd_acceptable(void *expv, struct dentry *dentry)
/* make sure parents give x permission to user */
int err;
parent = dget_parent(tdentry);
- err = permission(parent->d_inode, S_IXOTH);
+ err = permission(parent->d_inode, S_IXOTH, NULL);
if (err < 0) {
dput(parent);
break;
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8759cb1076ad..663f4839cc33 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -924,7 +924,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
err = nfserr_perm;
switch (type) {
case S_IFREG:
- err = vfs_create(dirp, dchild, iap->ia_mode);
+ err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
break;
case S_IFDIR:
err = vfs_mkdir(dirp, dchild, iap->ia_mode);
@@ -1067,7 +1067,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out;
}
- err = vfs_create(dirp, dchild, iap->ia_mode);
+ err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
if (err < 0)
goto out_nfserr;
@@ -1584,12 +1584,12 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
inode->i_uid == current->fsuid)
return 0;
- err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC));
+ err = permission(inode, acc & (MAY_READ|MAY_WRITE|MAY_EXEC), NULL);
/* Allow read access to binaries even when mode 111 */
if (err == -EACCES && S_ISREG(inode->i_mode) &&
acc == (MAY_READ | MAY_OWNER_OVERRIDE))
- err = permission(inode, MAY_EXEC);
+ err = permission(inode, MAY_EXEC, NULL);
return err? nfserrno(err) : 0;
}
diff --git a/fs/ntfs/namei.c b/fs/ntfs/namei.c
index 84d43247ba6e..a8c6e8a4e3b8 100644
--- a/fs/ntfs/namei.c
+++ b/fs/ntfs/namei.c
@@ -29,6 +29,7 @@
* ntfs_lookup - find the inode represented by a dentry in a directory inode
* @dir_ino: directory inode in which to look for the inode
* @dent: dentry representing the inode to look for
+ * @nd: lookup nameidata
*
* In short, ntfs_lookup() looks for the inode represented by the dentry @dent
* in the directory inode @dir_ino and if found attaches the inode to the
@@ -87,7 +88,7 @@
* name. We then convert the name to the current NLS code page, and proceed
* searching for a dentry with this name, etc, as in case 2), above.
*/
-static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent)
+static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent, struct nameidata *nd)
{
ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
struct inode *dent_inode;
diff --git a/fs/open.c b/fs/open.c
index 2e2e4e4dae97..8a4197969f27 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -219,7 +219,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
if (!S_ISREG(inode->i_mode))
goto dput_and_out;
- error = permission(inode,MAY_WRITE);
+ error = permission(inode,MAY_WRITE,&nd);
if (error)
goto dput_and_out;
@@ -365,7 +365,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else {
if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
+ (error = permission(inode,MAY_WRITE,&nd)) != 0)
goto dput_and_out;
}
down(&inode->i_sem);
@@ -410,7 +410,7 @@ long do_utimes(char __user * filename, struct timeval * times)
newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
} else {
if (current->fsuid != inode->i_uid &&
- (error = permission(inode,MAY_WRITE)) != 0)
+ (error = permission(inode,MAY_WRITE,&nd)) != 0)
goto dput_and_out;
}
down(&inode->i_sem);
@@ -467,9 +467,9 @@ asmlinkage long sys_access(const char __user * filename, int mode)
else
current->cap_effective = current->cap_permitted;
- res = user_path_walk(filename, &nd);
+ res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
if (!res) {
- res = permission(nd.dentry->d_inode, mode);
+ res = permission(nd.dentry->d_inode, mode, &nd);
/* SuS v2 requires we report a read only fs too */
if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
&& !special_file(nd.dentry->d_inode->i_mode))
@@ -493,7 +493,7 @@ asmlinkage long sys_chdir(const char __user * filename)
if (error)
goto out;
- error = permission(nd.dentry->d_inode,MAY_EXEC);
+ error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
if (error)
goto dput_and_out;
@@ -526,7 +526,7 @@ asmlinkage long sys_fchdir(unsigned int fd)
if (!S_ISDIR(inode->i_mode))
goto out_putf;
- error = permission(inode, MAY_EXEC);
+ error = permission(inode, MAY_EXEC, NULL);
if (!error)
set_fs_pwd(current->fs, mnt, dentry);
out_putf:
@@ -544,7 +544,7 @@ asmlinkage long sys_chroot(const char __user * filename)
if (error)
goto out;
- error = permission(nd.dentry->d_inode,MAY_EXEC);
+ error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
if (error)
goto dput_and_out;
@@ -952,11 +952,8 @@ int filp_close(struct file *filp, fl_owner_t id)
return 0;
}
retval = 0;
- if (filp->f_op && filp->f_op->flush) {
- lock_kernel();
+ if (filp->f_op && filp->f_op->flush)
retval = filp->f_op->flush(filp);
- unlock_kernel();
- }
dnotify_flush(filp, id);
locks_remove_posix(filp, id);
fput(filp);
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index 5a1fb89449be..c0df469c9dc6 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -59,9 +59,9 @@ static char *alias_names [ALIASES_NNODES];
#define NODE2INO(node) (node + OPENPROM_FIRST_INO)
#define NODEP2INO(no) (no + OPENPROM_FIRST_INO + last_node)
-static int openpromfs_create (struct inode *, struct dentry *, int);
+static int openpromfs_create (struct inode *, struct dentry *, int, struct nameidata *);
static int openpromfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry);
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *dentry, struct nameidata *nd);
static int openpromfs_unlink (struct inode *, struct dentry *dentry);
static ssize_t nodenum_read(struct file *file, char *buf,
@@ -639,7 +639,7 @@ static int lookup_children(u16 n, const char * name, int len)
return 0;
}
-static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *openpromfs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
int ino = 0;
#define OPFSL_DIR 0
@@ -854,7 +854,8 @@ out:
return 0;
}
-static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode)
+static int openpromfs_create (struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
char *p;
struct inode *inode;
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e843c6584cc9..485ff692e87f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -334,7 +334,7 @@ out:
goto exit;
}
-static int proc_permission(struct inode *inode, int mask)
+static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
{
if (vfs_permission(inode, mask) != 0)
return -EACCES;
@@ -864,7 +864,7 @@ out_unlock:
* directory. In this case, however, we can do it - no aliasing problems
* due to the way we treat inodes.
*/
-static int pid_revalidate(struct dentry * dentry, int flags)
+static int pid_revalidate(struct dentry * dentry, struct nameidata *nd)
{
if (pid_alive(proc_task(dentry->d_inode)))
return 1;
@@ -872,7 +872,7 @@ static int pid_revalidate(struct dentry * dentry, int flags)
return 0;
}
-static int pid_fd_revalidate(struct dentry * dentry, int flags)
+static int pid_fd_revalidate(struct dentry * dentry, struct nameidata *nd)
{
struct task_struct *task = proc_task(dentry->d_inode);
int fd = proc_type(dentry->d_inode) - PROC_PID_FD_DIR;
@@ -961,7 +961,7 @@ out:
}
/* SMP-safe */
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry)
+static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
struct task_struct *task = proc_task(dir);
unsigned fd = name_to_int(dentry);
@@ -1219,7 +1219,7 @@ out:
return ERR_PTR(error);
}
-static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){
+static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
return proc_pident_lookup(dir, dentry, base_stuff);
}
@@ -1245,7 +1245,9 @@ static struct file_operations proc_attr_operations = {
.readdir = proc_attr_readdir,
};
-static struct dentry *proc_attr_lookup(struct inode *dir, struct dentry *dentry){
+static struct dentry *proc_attr_lookup(struct inode *dir,
+ struct dentry *dentry, struct nameidata *nd)
+{
return proc_pident_lookup(dir, dentry, attr_stuff);
}
@@ -1326,7 +1328,7 @@ void proc_pid_flush(struct dentry *proc_dentry)
}
/* SMP-safe */
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct task_struct *task;
struct inode *inode;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 6f658ceafc3a..979237c72966 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -336,7 +336,7 @@ static struct dentry_operations proc_dentry_operations =
* Don't create negative dentries here, return -ENOENT by hand
* instead.
*/
-struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry)
+struct dentry *proc_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
struct proc_dir_entry * de;
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index 1268f3883f4e..eed19a3ea677 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -497,11 +497,10 @@ static int ds1286_read_proc(char *page, char **start, off_t off,
static int locks_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
- int len;
- lock_kernel();
- len = get_locks_status(page, start, off, count);
- unlock_kernel();
- if (len < count) *eof = 1;
+ int len = get_locks_status(page, start, off, count);
+
+ if (len < count)
+ *eof = 1;
return len;
}
diff --git a/fs/proc/root.c b/fs/proc/root.c
index f6b7c065a969..936962d01c28 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -79,19 +79,21 @@ void __init proc_root_init(void)
proc_bus = proc_mkdir("bus", 0);
}
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
- if (dir->i_ino == PROC_ROOT_INO) { /* check for safety... */
- lock_kernel();
+ /*
+ * nr_threads is actually protected by the tasklist_lock;
+ * however, it's conventional to do reads, especially for
+ * reporting, without any locking whatsoever.
+ */
+ if (dir->i_ino == PROC_ROOT_INO) /* check for safety... */
dir->i_nlink = proc_root.nlink + nr_threads;
- unlock_kernel();
- }
- if (!proc_lookup(dir, dentry)) {
+ if (!proc_lookup(dir, dentry, nd)) {
return NULL;
}
- return proc_pid_lookup(dir, dentry);
+ return proc_pid_lookup(dir, dentry, nd);
}
static int proc_root_readdir(struct file * filp,
diff --git a/fs/qnx4/namei.c b/fs/qnx4/namei.c
index 0a7592c5b958..36e903d89777 100644
--- a/fs/qnx4/namei.c
+++ b/fs/qnx4/namei.c
@@ -107,7 +107,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
return NULL;
}
-struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry)
+struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
int ino;
struct qnx4_inode_entry *de;
@@ -142,7 +142,8 @@ out:
}
#ifdef CONFIG_QNX4FS_RW
-int qnx4_create(struct inode *dir, struct dentry *dentry, int mode)
+int qnx4_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
QNX4DEBUG(("qnx4: qnx4_create\n"));
if (dir == NULL) {
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 372f06515900..362ee3135e69 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -111,7 +111,7 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
return retval;
}
-static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
}
@@ -146,6 +146,7 @@ static struct file_operations ramfs_file_operations = {
.mmap = generic_file_mmap,
.fsync = simple_sync_file,
.sendfile = generic_file_sendfile,
+ .llseek = generic_file_llseek,
};
static struct inode_operations ramfs_file_inode_operations = {
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 46bc6549577d..93151fb285c0 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -316,7 +316,7 @@ static int reiserfs_find_entry (struct inode * dir, const char * name, int namel
}
-static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry)
+static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
int retval;
struct inode * inode = NULL;
@@ -558,7 +558,8 @@ static int new_inode_init(struct inode *inode, struct inode *dir, int mode) {
return 0 ;
}
-static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode)
+static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
int retval;
struct inode * inode;
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c
index fb60389d42fc..24cd428a521e 100644
--- a/fs/romfs/inode.c
+++ b/fs/romfs/inode.c
@@ -329,7 +329,7 @@ out:
}
static struct dentry *
-romfs_lookup(struct inode *dir, struct dentry *dentry)
+romfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
unsigned long offset, maxoff;
int fslen, res;
diff --git a/fs/smbfs/dir.c b/fs/smbfs/dir.c
index af4b42beab8f..f0b62740ae89 100644
--- a/fs/smbfs/dir.c
+++ b/fs/smbfs/dir.c
@@ -24,8 +24,8 @@
static int smb_readdir(struct file *, void *, filldir_t);
static int smb_dir_open(struct inode *, struct file *);
-static struct dentry *smb_lookup(struct inode *, struct dentry *);
-static int smb_create(struct inode *, struct dentry *, int);
+static struct dentry *smb_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int smb_create(struct inode *, struct dentry *, int, struct nameidata *);
static int smb_mkdir(struct inode *, struct dentry *, int);
static int smb_rmdir(struct inode *, struct dentry *);
static int smb_unlink(struct inode *, struct dentry *);
@@ -268,7 +268,7 @@ smb_dir_open(struct inode *dir, struct file *file)
/*
* Dentry operations routines
*/
-static int smb_lookup_validate(struct dentry *, int);
+static int smb_lookup_validate(struct dentry *, struct nameidata *);
static int smb_hash_dentry(struct dentry *, struct qstr *);
static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
static int smb_delete_dentry(struct dentry *);
@@ -292,7 +292,7 @@ static struct dentry_operations smbfs_dentry_operations_case =
* This is the callback when the dcache has a lookup hit.
*/
static int
-smb_lookup_validate(struct dentry * dentry, int flags)
+smb_lookup_validate(struct dentry * dentry, struct nameidata *nd)
{
struct smb_sb_info *server = server_from_dentry(dentry);
struct inode * inode = dentry->d_inode;
@@ -420,7 +420,7 @@ smb_renew_times(struct dentry * dentry)
}
static struct dentry *
-smb_lookup(struct inode *dir, struct dentry *dentry)
+smb_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct smb_fattr finfo;
struct inode *inode;
@@ -510,7 +510,8 @@ out_close:
/* N.B. How should the mode argument be used? */
static int
-smb_create(struct inode *dir, struct dentry *dentry, int mode)
+smb_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
struct smb_sb_info *server = server_from_dentry(dentry);
__u16 fileid;
diff --git a/fs/smbfs/file.c b/fs/smbfs/file.c
index a174775b2d13..6b25d7c89177 100644
--- a/fs/smbfs/file.c
+++ b/fs/smbfs/file.c
@@ -367,7 +367,7 @@ smb_file_release(struct inode *inode, struct file * file)
* privileges, so we need our own check for this.
*/
static int
-smb_file_permission(struct inode *inode, int mask)
+smb_file_permission(struct inode *inode, int mask, struct nameidata *nd)
{
int mode = inode->i_mode;
int error = 0;
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index e5439f1aafa5..7f0d265d0bb9 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -2,6 +2,8 @@
* bin.c - binary file operations for sysfs.
*/
+#undef DEBUG
+
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kobject.h>
@@ -42,18 +44,17 @@ read(struct file * file, char __user * userbuf, size_t count, loff_t * off)
ret = fill_read(dentry, buffer, offs, count);
if (ret < 0)
- goto Done;
+ return ret;
count = ret;
- ret = -EFAULT;
- if (copy_to_user(userbuf, buffer, count) != 0)
- goto Done;
+ if (copy_to_user(userbuf, buffer + offs, count) != 0)
+ return -EINVAL;
+
+ pr_debug("offs = %lld, *off = %lld, count = %zd\n", offs, *off, count);
*off = offs + count;
- ret = count;
- Done:
- return ret;
+ return count;
}
static int
@@ -72,7 +73,6 @@ static ssize_t write(struct file * file, const char __user * userbuf,
struct dentry *dentry = file->f_dentry;
int size = dentry->d_inode->i_size;
loff_t offs = *off;
- int ret;
if (count > PAGE_SIZE)
count = PAGE_SIZE;
@@ -83,16 +83,13 @@ static ssize_t write(struct file * file, const char __user * userbuf,
count = size - offs;
}
- ret = -EFAULT;
- if (copy_from_user(buffer, userbuf, count))
- goto Done;
+ if (copy_from_user(buffer + offs, userbuf, count))
+ return -EFAULT;
count = flush_write(dentry, buffer, offs, count);
if (count > 0)
*off = offs + count;
- ret = count;
- Done:
- return ret;
+ return count;
}
static int open(struct inode * inode, struct file * file)
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 1ca3a06db1df..0b1588ab9259 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -121,7 +121,29 @@ void sysfs_remove_dir(struct kobject * kobj)
dput(parent);
}
+void sysfs_rename_dir(struct kobject * kobj, char *new_name)
+{
+ struct dentry * new_dentry, * parent;
+
+ if (!strcmp(kobj->name, new_name))
+ return;
+
+ if (!kobj->parent)
+ return;
+
+ parent = kobj->parent->dentry;
+
+ down(&parent->d_inode->i_sem);
+
+ new_dentry = sysfs_get_dentry(parent, new_name);
+ d_move(kobj->dentry, new_dentry);
+
+ strlcpy(kobj->name, new_name, KOBJ_NAME_LEN);
+
+ up(&parent->d_inode->i_sem);
+}
EXPORT_SYMBOL(sysfs_create_dir);
EXPORT_SYMBOL(sysfs_remove_dir);
+EXPORT_SYMBOL(sysfs_rename_dir);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 1d25a84702b2..2cedefe8c4a0 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -247,6 +247,12 @@ static int check_perm(struct inode * inode, struct file * file)
if (!kobj || !attr)
goto Einval;
+ /* Grab the module reference for this attribute if we have one */
+ if (!try_module_get(attr->owner)) {
+ error = -ENODEV;
+ goto Done;
+ }
+
/* if the kobject has no ktype, then we assume that it is a subsystem
* itself, and use ops for it.
*/
@@ -300,6 +306,7 @@ static int check_perm(struct inode * inode, struct file * file)
goto Done;
Eaccess:
error = -EACCES;
+ module_put(attr->owner);
Done:
if (error && kobj)
kobject_put(kobj);
@@ -314,10 +321,12 @@ static int sysfs_open_file(struct inode * inode, struct file * filp)
static int sysfs_release(struct inode * inode, struct file * filp)
{
struct kobject * kobj = filp->f_dentry->d_parent->d_fsdata;
+ struct attribute * attr = filp->f_dentry->d_fsdata;
struct sysfs_buffer * buffer = filp->private_data;
if (kobj)
kobject_put(kobj);
+ module_put(attr->owner);
if (buffer) {
if (buffer->page)
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index f2988f107696..cbf08f04d07c 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -64,7 +64,7 @@ struct dentry_operations sysv_dentry_operations = {
.d_hash = sysv_hash,
};
-static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry)
+static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
struct inode * inode = NULL;
ino_t ino;
@@ -96,7 +96,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, int mode, dev_
return err;
}
-static int sysv_create(struct inode * dir, struct dentry * dentry, int mode)
+static int sysv_create(struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd)
{
return sysv_mknod(dir, dentry, mode, 0);
}
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 9fd46aff63ae..b1cf9999e902 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -188,7 +188,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
{
int result = -EINVAL;
- if ( permission(inode, MAY_READ) != 0 )
+ if ( permission(inode, MAY_READ, NULL) != 0 )
{
udf_debug("no permission to access inode %lu\n",
inode->i_ino);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index b5be4880deac..d2ac88dae447 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -289,6 +289,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
* PRE-CONDITIONS
* dir Pointer to inode of parent directory.
* dentry Pointer to dentry to complete.
+ * nd Pointer to lookup nameidata
*
* POST-CONDITIONS
* <return> Zero on success.
@@ -299,7 +300,7 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
*/
static struct dentry *
-udf_lookup(struct inode *dir, struct dentry *dentry)
+udf_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode *inode = NULL;
struct fileIdentDesc cfi, *fi;
@@ -620,7 +621,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
}
-static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
+static int udf_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
struct udf_fileident_bh fibh;
struct inode *inode;
diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c
index 24c6c5d2938d..82f391298c48 100644
--- a/fs/ufs/namei.c
+++ b/fs/ufs/namei.c
@@ -62,7 +62,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
return err;
}
-static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry)
+static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode = NULL;
ino_t ino;
@@ -92,7 +92,8 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry)
* If the create succeeds, we fill in the inode information
* with d_instantiate().
*/
-static int ufs_create (struct inode * dir, struct dentry * dentry, int mode)
+static int ufs_create (struct inode * dir, struct dentry * dentry, int mode,
+ struct nameidata *nd)
{
struct inode * inode = ufs_new_inode(dir, mode);
int err = PTR_ERR(inode);
diff --git a/fs/umsdos/dir.c b/fs/umsdos/dir.c
index befb7545f53c..775f02021128 100644
--- a/fs/umsdos/dir.c
+++ b/fs/umsdos/dir.c
@@ -30,7 +30,7 @@ extern struct inode *pseudo_root;
*/
/* nothing for now ... */
-static int umsdos_dentry_validate(struct dentry *dentry, int flags)
+static int umsdos_dentry_validate(struct dentry *dentry, struct nameidata *nd)
{
return 1;
}
@@ -564,7 +564,7 @@ out_remove:
* Called by VFS; should fill dentry->d_inode via d_add.
*/
-struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry)
+struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
struct dentry *ret;
diff --git a/fs/umsdos/emd.c b/fs/umsdos/emd.c
index 06190391d47e..7fadb55b7e44 100644
--- a/fs/umsdos/emd.c
+++ b/fs/umsdos/emd.c
@@ -105,7 +105,7 @@ int umsdos_make_emd(struct dentry *parent)
Printk(("umsdos_make_emd: creating EMD %s/%s\n",
parent->d_name.name, demd->d_name.name));
- err = msdos_create(parent->d_inode, demd, S_IFREG | 0777);
+ err = msdos_create(parent->d_inode, demd, S_IFREG | 0777, NULL);
if (err) {
printk (KERN_WARNING
"umsdos_make_emd: create %s/%s failed, err=%d\n",
diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c
index 3d89ba970a06..2d8a64af1aed 100644
--- a/fs/umsdos/namei.c
+++ b/fs/umsdos/namei.c
@@ -274,7 +274,7 @@ static int umsdos_create_any (struct inode *dir, struct dentry *dentry,
if (fake->d_inode)
goto out_remove_dput;
- ret = msdos_create (dir, fake, S_IFREG | 0777);
+ ret = msdos_create (dir, fake, S_IFREG | 0777, NULL);
if (ret)
goto out_remove_dput;
@@ -311,7 +311,7 @@ out_remove:
*
* Return the status of the operation. 0 mean success.
*/
-int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode)
+int UMSDOS_create (struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
{
return umsdos_create_any (dir, dentry, mode, 0, 0);
}
diff --git a/fs/umsdos/rdir.c b/fs/umsdos/rdir.c
index d4ac89d1e668..2f32539b1a37 100644
--- a/fs/umsdos/rdir.c
+++ b/fs/umsdos/rdir.c
@@ -101,7 +101,7 @@ struct dentry *umsdos_rlookup_x ( struct inode *dir, struct dentry *dentry, int
goto out;
}
- ret = msdos_lookup (dir, dentry);
+ ret = msdos_lookup (dir, dentry, NULL);
if (ret) {
printk(KERN_WARNING
"umsdos_rlookup_x: %s/%s failed, ret=%ld\n",
@@ -129,7 +129,7 @@ out:
}
-struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry)
+struct dentry *UMSDOS_rlookup ( struct inode *dir, struct dentry *dentry, struct nameidata *nd)
{
return umsdos_rlookup_x (dir, dentry, 0);
}
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index 1f83a9d77e8a..12c067c8355d 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -45,7 +45,7 @@ static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
static int vfat_hash(struct dentry *parent, struct qstr *qstr);
static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
-static int vfat_revalidate(struct dentry *dentry, int);
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd);
static struct dentry_operations vfat_dentry_ops[4] = {
{
@@ -68,7 +68,7 @@ static struct dentry_operations vfat_dentry_ops[4] = {
}
};
-static int vfat_revalidate(struct dentry *dentry, int flags)
+static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
{
PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
spin_lock(&dcache_lock);
@@ -860,7 +860,7 @@ static int vfat_find(struct inode *dir,struct qstr* qname,
return res ? res : -ENOENT;
}
-struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
+struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry, struct nameidata *nd)
{
int res;
struct vfat_slot_info sinfo;
@@ -912,7 +912,8 @@ error:
return dentry;
}
-int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
+int vfat_create(struct inode *dir,struct dentry* dentry,int mode,
+ struct nameidata *nd)
{
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
diff --git a/fs/xattr.c b/fs/xattr.c
index 2a2b6d53af1e..37d2a109eef7 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -160,9 +160,7 @@ getxattr(struct dentry *d, char *name, void *value, size_t size)
error = security_inode_getxattr(d, kname);
if (error)
goto out;
- down(&d->d_inode->i_sem);
error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
- up(&d->d_inode->i_sem);
}
if (kvalue && error > 0)
@@ -233,9 +231,7 @@ listxattr(struct dentry *d, char *list, size_t size)
error = security_inode_listxattr(d);
if (error)
goto out;
- down(&d->d_inode->i_sem);
error = d->d_inode->i_op->listxattr(d, klist, size);
- up(&d->d_inode->i_sem);
}
if (klist && error > 0)
diff --git a/fs/xfs/linux/xfs_iops.c b/fs/xfs/linux/xfs_iops.c
index 14d393eb6d2e..59f520390143 100644
--- a/fs/xfs/linux/xfs_iops.c
+++ b/fs/xfs/linux/xfs_iops.c
@@ -175,7 +175,8 @@ STATIC int
linvfs_create(
struct inode *dir,
struct dentry *dentry,
- int mode)
+ int mode,
+ struct nameidata *nd)
{
return linvfs_mknod(dir, dentry, mode, 0);
}
@@ -192,7 +193,8 @@ linvfs_mkdir(
STATIC struct dentry *
linvfs_lookup(
struct inode *dir,
- struct dentry *dentry)
+ struct dentry *dentry,
+ struct nameidata *nd)
{
struct inode *ip = NULL;
vnode_t *vp, *cvp = NULL;
@@ -429,7 +431,8 @@ linvfs_follow_link(
STATIC int
linvfs_permission(
struct inode *inode,
- int mode)
+ int mode,
+ struct nameidata *nd)
{
vnode_t *vp = LINVFS_GET_VP(inode);
int error;
@@ -639,7 +642,7 @@ linvfs_setxattr(
}
STATIC ssize_t
-linvfs_getxattr(
+__linvfs_getxattr(
struct dentry *dentry,
const char *name,
void *data,
@@ -694,9 +697,24 @@ linvfs_getxattr(
return -EOPNOTSUPP;
}
+STATIC ssize_t
+linvfs_getxattr(
+ struct dentry *dentry,
+ const char *name,
+ void *data,
+ size_t size)
+{
+ int error;
+
+ down(&dentry->d_inode->i_sem);
+ error = __linvfs_getxattr(dentry, name, data, size);
+ up(&dentry->d_inode->i_sem);
+
+ return error;
+}
STATIC ssize_t
-linvfs_listxattr(
+__linvfs_listxattr(
struct dentry *dentry,
char *data,
size_t size)
@@ -738,6 +756,21 @@ linvfs_listxattr(
return result;
}
+STATIC ssize_t
+linvfs_listxattr(
+ struct dentry *dentry,
+ char *data,
+ size_t size)
+{
+ int error;
+
+ down(&dentry->d_inode->i_sem);
+ error = __linvfs_listxattr(dentry, data, size);
+ up(&dentry->d_inode->i_sem);
+
+ return error;
+}
+
STATIC int
linvfs_removexattr(
struct dentry *dentry,
diff --git a/fs/xfs/linux/xfs_super.c b/fs/xfs/linux/xfs_super.c
index 0df0d915865f..d482cb69fade 100644
--- a/fs/xfs/linux/xfs_super.c
+++ b/fs/xfs/linux/xfs_super.c
@@ -265,8 +265,8 @@ xfs_setsize_buftarg(
if (set_blocksize(btp->pbr_bdev, sectorsize)) {
printk(KERN_WARNING
- "XFS: Cannot set_blocksize to %u on device 0x%x\n",
- sectorsize, btp->pbr_dev);
+ "XFS: Cannot set_blocksize to %u on device 0x%lx\n",
+ sectorsize, (unsigned long)btp->pbr_dev);
}
}
diff --git a/include/asm-alpha/div64.h b/include/asm-alpha/div64.h
index 080dcd480805..6cd978cefb28 100644
--- a/include/asm-alpha/div64.h
+++ b/include/asm-alpha/div64.h
@@ -1,14 +1 @@
-#ifndef __ALPHA_DIV64
-#define __ALPHA_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) (n)) % (unsigned) (base); \
- (n) = ((unsigned long) (n)) / (unsigned) (base); \
- __res; })
-
-#endif
+#include <asm-generic/div64.h>
diff --git a/include/asm-alpha/machvec.h b/include/asm-alpha/machvec.h
index 6d1b408e3ed5..f09f71909aa6 100644
--- a/include/asm-alpha/machvec.h
+++ b/include/asm-alpha/machvec.h
@@ -68,7 +68,7 @@ struct alpha_machine_vector
int (*mv_is_ioaddr)(unsigned long);
void (*mv_switch_mm)(struct mm_struct *, struct mm_struct *,
- struct task_struct *, long);
+ struct task_struct *);
void (*mv_activate_mm)(struct mm_struct *, struct mm_struct *);
void (*mv_flush_tlb_current)(struct mm_struct *);
diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h
index a087254ea38a..3ae6408acaed 100644
--- a/include/asm-alpha/mmu_context.h
+++ b/include/asm-alpha/mmu_context.h
@@ -130,11 +130,12 @@ __get_new_mm_context(struct mm_struct *mm, long cpu)
__EXTERN_INLINE void
ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
- struct task_struct *next, long cpu)
+ struct task_struct *next)
{
/* Check if our ASN is of an older version, and thus invalid. */
unsigned long asn;
unsigned long mmc;
+ long cpu = smp_processor_id();
#ifdef CONFIG_SMP
cpu_data[cpu].asn_lock = 1;
@@ -159,7 +160,7 @@ ev5_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
__EXTERN_INLINE void
ev4_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
- struct task_struct *next, long cpu)
+ struct task_struct *next)
{
/* As described, ASN's are broken for TLB usage. But we can
optimize for switching between threads -- if the mm is
@@ -174,7 +175,7 @@ ev4_switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm,
/* Do continue to allocate ASNs, because we can still use them
to avoid flushing the icache. */
- ev5_switch_mm(prev_mm, next_mm, next, cpu);
+ ev5_switch_mm(prev_mm, next_mm, next);
}
extern void __load_new_mm_context(struct mm_struct *);
@@ -212,14 +213,14 @@ ev4_activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm)
#define deactivate_mm(tsk,mm) do { } while (0)
#ifdef CONFIG_ALPHA_GENERIC
-# define switch_mm(a,b,c,d) alpha_mv.mv_switch_mm((a),(b),(c),(d))
+# define switch_mm(a,b,c) alpha_mv.mv_switch_mm((a),(b),(c))
# define activate_mm(x,y) alpha_mv.mv_activate_mm((x),(y))
#else
# ifdef CONFIG_ALPHA_EV4
-# define switch_mm(a,b,c,d) ev4_switch_mm((a),(b),(c),(d))
+# define switch_mm(a,b,c) ev4_switch_mm((a),(b),(c))
# define activate_mm(x,y) ev4_activate_mm((x),(y))
# else
-# define switch_mm(a,b,c,d) ev5_switch_mm((a),(b),(c),(d))
+# define switch_mm(a,b,c) ev5_switch_mm((a),(b),(c))
# define activate_mm(x,y) ev5_activate_mm((x),(y))
# endif
#endif
@@ -245,7 +246,7 @@ destroy_context(struct mm_struct *mm)
}
static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
tsk->thread_info->pcb.ptbr
= ((unsigned long)mm->pgd - IDENT_ADDR) >> PAGE_SHIFT;
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index 6edb9c64aa7b..36e3130c6696 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -31,7 +31,6 @@ extern pg_data_t node_data[];
#define pa_to_nid(pa) alpha_pa_to_nid(pa)
#define NODE_DATA(nid) (&node_data[(nid)])
-#define node_size(nid) (NODE_DATA(nid)->node_size)
#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
@@ -124,7 +123,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
#define pfn_to_nid(pfn) pa_to_nid(((u64)pfn << PAGE_SHIFT))
#define pfn_valid(pfn) \
(((pfn) - node_start_pfn(pfn_to_nid(pfn))) < \
- node_size(pfn_to_nid(pfn))) \
+ node_spanned_pages(pfn_to_nid(pfn))) \
#define virt_addr_valid(kaddr) pfn_valid((__pa(kaddr) >> PAGE_SHIFT))
diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h
index 3b3b473c668f..e0340f5fbf32 100644
--- a/include/asm-arm/mmu_context.h
+++ b/include/asm-arm/mmu_context.h
@@ -28,7 +28,7 @@
* tsk->mm will be NULL
*/
static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -40,7 +40,7 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
*/
static inline void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned int cpu)
+ struct task_struct *tsk)
{
if (prev != next) {
cpu_switch_mm(next->pgd, next);
diff --git a/include/asm-arm26/arch.h b/include/asm-arm26/arch.h
deleted file mode 100644
index 1011bcc6d7ac..000000000000
--- a/include/asm-arm26/arch.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * linux/include/asm-arm/mach/arch.h
- *
- * Copyright (C) 2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/*
- * The size of struct machine_desc
- * (for assembler code)
- * FIXME - I count 45... or is this padding?
- */
-#define SIZEOF_MACHINE_DESC 48
-
-#ifndef __ASSEMBLY__
-
-struct tag;
-
-struct machine_desc {
- int nr; /* arch no FIXME - get rid */
- const char *name; /* architecture name */
- unsigned int param_offset; /* parameter page */
-
- unsigned int video_start; /* start of video RAM */
- unsigned int video_end; /* end of video RAM */
-
- unsigned int reserve_lp0 :1; /* never has lp0 */
- unsigned int reserve_lp1 :1; /* never has lp1 */
- unsigned int reserve_lp2 :1; /* never has lp2 */
- unsigned int soft_reboot :1; /* soft reboot */
- void (*fixup)(struct machine_desc *,
- struct tag *, char **,
- struct meminfo *);
- void (*map_io)(void);/* IO mapping function */
- void (*init_irq)(void);
-};
-
-/*
- * Set of macros to define architecture features. This is built into
- * a table by the linker.
- */
-#define MACHINE_START(_type,_name) \
-const struct machine_desc __mach_desc_##_type \
- __attribute__((__section__(".arch.info"))) = { \
- nr: MACH_TYPE_##_type, \
- name: _name,
-
-#define MAINTAINER(n)
-
-#define BOOT_PARAMS(_params) \
- param_offset: _params,
-
-#define INITIRQ(_func) \
- init_irq: _func,
-
-#define MACHINE_END \
-};
-
-#endif
diff --git a/include/asm-arm26/bug.h b/include/asm-arm26/bug.h
index a92b1bc8eb1e..a1afde728b03 100644
--- a/include/asm-arm26/bug.h
+++ b/include/asm-arm26/bug.h
@@ -4,7 +4,7 @@
#include <linux/config.h>
#ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void __bug(const char *file, int line, void *data);
+extern volatile void __bug(const char *file, int line, void *data);
/* give file/line information */
#define BUG() __bug(__FILE__, __LINE__, NULL)
@@ -18,4 +18,13 @@ extern void __bug(const char *file, int line, void *data);
#endif
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+
+#define WARN_ON(condition) do { \
+ if (unlikely((condition)!=0)) { \
+ printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+ dump_stack(); \
+ } \
+} while (0)
+
#endif
diff --git a/include/asm-arm26/bugs.h b/include/asm-arm26/bugs.h
index 665ab62c27ce..e99ac2e46d7f 100644
--- a/include/asm-arm26/bugs.h
+++ b/include/asm-arm26/bugs.h
@@ -1,5 +1,5 @@
/*
- * linux/include/asm-arm/bugs.h
+ * linux/include/asm-arm26/bugs.h
*
* Copyright (C) 1995 Russell King
*
diff --git a/include/asm-arm26/div64.h b/include/asm-arm26/div64.h
index 27fec4ee6aed..6cd978cefb28 100644
--- a/include/asm-arm26/div64.h
+++ b/include/asm-arm26/div64.h
@@ -1,14 +1 @@
-#ifndef __ASM_ARM_DIV64
-#define __ASM_ARM_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) \
-({ \
- int __res; \
- __res = ((unsigned long)n) % (unsigned int)base; \
- n = ((unsigned long)n) / (unsigned int)base; \
- __res; \
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff --git a/include/asm-arm26/ecard.h b/include/asm-arm26/ecard.h
index 28af14fd7f75..8318a0c1df81 100644
--- a/include/asm-arm26/ecard.h
+++ b/include/asm-arm26/ecard.h
@@ -26,6 +26,9 @@
#define PROD_ACORN_ETHER1 0x0003
#define PROD_ACORN_MFM 0x000b
+#define MANU_CCONCEPTS 0x0009
+#define PROD_CCONCEPTS_COLOURCARD 0x0050
+
#define MANU_ANT2 0x0011
#define PROD_ANT_ETHER3 0x00a4
diff --git a/include/asm-arm26/mach-types.h b/include/asm-arm26/mach-types.h
index 514b8032696c..b34045b78128 100644
--- a/include/asm-arm26/mach-types.h
+++ b/include/asm-arm26/mach-types.h
@@ -1,5 +1,6 @@
/*
* Unlike ARM32 this is NOT automatically generated. DONT delete it
+ * Instead, consider FIXME-ing it so its auto-detected.
*/
#ifndef __ASM_ARM_MACH_TYPE_H
diff --git a/include/asm-arm26/mmu_context.h b/include/asm-arm26/mmu_context.h
index 88b7b4f8f210..1a929bfe5c3a 100644
--- a/include/asm-arm26/mmu_context.h
+++ b/include/asm-arm26/mmu_context.h
@@ -26,7 +26,7 @@
* tsk->mm will be NULL
*/
static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -36,7 +36,7 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
*/
static inline void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned int cpu)
+ struct task_struct *tsk)
{
cpu_switch_mm(next->pgd, next);
}
diff --git a/include/asm-arm26/pgalloc.h b/include/asm-arm26/pgalloc.h
index bf2e19512524..6437167b1ffe 100644
--- a/include/asm-arm26/pgalloc.h
+++ b/include/asm-arm26/pgalloc.h
@@ -55,9 +55,9 @@ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
* is thrown away. It just cant be zero. -IM
*/
-#define pmd_alloc_one(mm,addr) ((pmd_t *)2); BUG()
+#define pmd_alloc_one(mm,addr) ({ BUG(); ((pmd_t *)2); })
#define pmd_free(pmd) do { } while (0)
-#define pgd_populate(mm,pmd,pte) (0)
+#define pgd_populate(mm,pmd,pte) BUG()
extern pgd_t *get_pgd_slow(struct mm_struct *mm);
extern void free_pgd_slow(pgd_t *pgd);
diff --git a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
index a6ac3957b0be..3fb067eaf801 100644
--- a/include/asm-arm26/pgtable.h
+++ b/include/asm-arm26/pgtable.h
@@ -179,7 +179,7 @@ extern struct page *empty_zero_page;
/* Is pmd_page supposed to return a pointer to a page in some arches? ours seems to
* return a pointer to memory (no special alignment)
*/
-#define pmd_page(pmd) ((unsigned long)(pmd_val((pmd)) & ~_PMD_PRESENT))
+#define pmd_page(pmd) ((struct page *)(pmd_val((pmd)) & ~_PMD_PRESENT))
#define pmd_page_kernel(pmd) ((pte_t *)(pmd_val((pmd)) & ~_PMD_PRESENT))
#define pte_offset_kernel(dir,addr) (pmd_page_kernel(*(dir)) + __pte_index(addr))
diff --git a/include/asm-arm26/statfs.h b/include/asm-arm26/statfs.h
index a1eba73ded99..776dbc8f7623 100644
--- a/include/asm-arm26/statfs.h
+++ b/include/asm-arm26/statfs.h
@@ -1,25 +1,8 @@
#ifndef _ASMARM_STATFS_H
#define _ASMARM_STATFS_H
-#ifndef __KERNEL_STRICT_NAMES
+//FIXME - this may not be appropriate for arm26. check it out.
-#include <linux/types.h>
-
-typedef __kernel_fsid_t fsid_t;
-
-#endif
-
-struct statfs {
- long f_type;
- long f_bsize;
- long f_blocks;
- long f_bfree;
- long f_bavail;
- long f_files;
- long f_ffree;
- __kernel_fsid_t f_fsid;
- long f_namelen;
- long f_spare[6];
-};
+#include <asm-generic/statfs.h>
#endif
diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
index 3f298bf9206a..24c5136484fb 100644
--- a/include/asm-arm26/thread_info.h
+++ b/include/asm-arm26/thread_info.h
@@ -85,7 +85,7 @@ static inline struct thread_info *current_thread_info(void)
//#define INIT_THREAD_SIZE (65536)
#define __get_user_regs(x) (((struct pt_regs *)((unsigned long)(x) + THREAD_SIZE - 8)) - 1)
-extern struct thread_info *alloc_thread_info(void);
+extern struct thread_info *alloc_thread_info(struct task_struct *task);
extern void free_thread_info(struct thread_info *);
#define get_thread_info(ti) get_task_struct((ti)->task)
diff --git a/include/asm-cris/div64.h b/include/asm-cris/div64.h
index bf33c2e8a04d..6cd978cefb28 100644
--- a/include/asm-cris/div64.h
+++ b/include/asm-cris/div64.h
@@ -1,16 +1 @@
-#ifndef __ASM_CRIS_DIV64
-#define __ASM_CRIS_DIV64
-
-/* copy from asm-arm */
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) \
-({ \
- int __res; \
- __res = ((unsigned long)n) % (unsigned int)base; \
- n = ((unsigned long)n) / (unsigned int)base; \
- __res; \
-})
-
-#endif
-
+#include <asm-generic/div64.h>
diff --git a/include/asm-cris/mmu_context.h b/include/asm-cris/mmu_context.h
index 6a6ea71a85cd..f9308c5bbd99 100644
--- a/include/asm-cris/mmu_context.h
+++ b/include/asm-cris/mmu_context.h
@@ -5,11 +5,11 @@ extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
extern void get_mmu_context(struct mm_struct *mm);
extern void destroy_context(struct mm_struct *mm);
extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, int cpu);
+ struct task_struct *tsk);
#define deactivate_mm(tsk,mm) do { } while (0)
-#define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id())
+#define activate_mm(prev,next) switch_mm((prev),(next),NULL)
/* current active pgd - this is similar to other processors pgd
* registers like cr3 on the i386
@@ -17,7 +17,7 @@ extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
extern volatile pgd_t *current_pgd; /* defined in arch/cris/mm/fault.c */
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h
new file mode 100644
index 000000000000..292b5a840431
--- /dev/null
+++ b/include/asm-generic/div64.h
@@ -0,0 +1,53 @@
+#ifndef _ASM_GENERIC_DIV64_H
+#define _ASM_GENERIC_DIV64_H
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h
+ *
+ * The semantics of do_div() are:
+ *
+ * uint32_t do_div(uint64_t *n, uint32_t base)
+ * {
+ * uint32_t remainder = *n % base;
+ * *n = *n / base;
+ * return remainder;
+ * }
+ *
+ * NOTE: macro parameter n is evaluated multiple times,
+ * beware of side effects!
+ */
+
+#include <linux/types.h>
+
+#if BITS_PER_LONG == 64
+
+# define do_div(n,base) ({ \
+ uint32_t __base = (base); \
+ uint32_t __rem; \
+ __rem = ((uint64_t)(n)) % __base; \
+ (n) = ((uint64_t)(n)) / __base; \
+ __rem; \
+ })
+
+#elif BITS_PER_LONG == 32
+
+extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor);
+
+# define do_div(n,base) ({ \
+ uint32_t __base = (base); \
+ uint32_t __rem; \
+ if (((n) >> 32) == 0) { \
+ __rem = (uint32_t)(n) % __base; \
+ (n) = (uint32_t)(n) / __base; \
+ } else \
+ __rem = __div64_32(&(n), __base); \
+ __rem; \
+ })
+
+#else /* BITS_PER_LONG == ?? */
+
+# error do_div() does not yet support the C64
+
+#endif /* BITS_PER_LONG */
+
+#endif /* _ASM_GENERIC_DIV64_H */
diff --git a/include/asm-h8300/div64.h b/include/asm-h8300/div64.h
index df5634def9dc..6cd978cefb28 100644
--- a/include/asm-h8300/div64.h
+++ b/include/asm-h8300/div64.h
@@ -1,13 +1 @@
-#ifndef H8300_DIV64_H
-#define H8300_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; \
-})
-
-#endif /* _H8300_DIV64_H */
+#include <asm-generic/div64.h>
diff --git a/include/asm-h8300/flat.h b/include/asm-h8300/flat.h
index ac3f50610f54..61d9aaf7e0b2 100644
--- a/include/asm-h8300/flat.h
+++ b/include/asm-h8300/flat.h
@@ -5,6 +5,21 @@
#ifndef __H8300_FLAT_H__
#define __H8300_FLAT_H__
-#define flat_argvp_envp_on_stack() 1
+#define flat_stack_align(sp) /* nothing needed */
+#define flat_argvp_envp_on_stack() 1
+#define flat_old_ram_flag(flags) 1
+#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
+
+/*
+ * on the H8 a couple of the relocations have an instruction in the
+ * top byte. As there can only be 24bits of address space, we just
+ * always preserve that 8bits at the top, when it isn't an instruction
+ * is is 0 (davidm@snapgear.com)
+ */
+
+#define flat_get_relocate_addr(rel) (rel)
+#define flat_get_addr_from_rp(rp, relval) (get_unaligned(rp) & 0x0ffffff)
+#define flat_put_addr_at_rp(rp, addr, rel) \
+ put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp)
#endif /* __H8300_FLAT_H__ */
diff --git a/include/asm-h8300/mmu_context.h b/include/asm-h8300/mmu_context.h
index ffdf723191cf..23b555b7b4b9 100644
--- a/include/asm-h8300/mmu_context.h
+++ b/include/asm-h8300/mmu_context.h
@@ -6,7 +6,7 @@
#include <asm/page.h>
#include <asm/pgalloc.h>
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -20,7 +20,7 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
#define destroy_context(mm) do { } while(0)
#define deactivate_mm(tsk,mm) do { } while(0)
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
}
diff --git a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
index adc632b97542..d3ce5511dbbc 100644
--- a/include/asm-i386/cacheflush.h
+++ b/include/asm-i386/cacheflush.h
@@ -17,4 +17,9 @@
void global_flush_tlb(void);
int change_page_attr(struct page *page, int numpages, pgprot_t prot);
+#ifdef CONFIG_DEBUG_PAGEALLOC
+/* internal debugging function */
+void kernel_map_pages(struct page *page, int numpages, int enable);
+#endif
+
#endif /* _I386_CACHEFLUSH_H */
diff --git a/include/asm-i386/hardirq.h b/include/asm-i386/hardirq.h
index e8b9149f0b29..5a14545af179 100644
--- a/include/asm-i386/hardirq.h
+++ b/include/asm-i386/hardirq.h
@@ -7,8 +7,6 @@
typedef struct {
unsigned int __softirq_pending;
- unsigned int __syscall_count;
- struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
unsigned long idle_timestamp;
unsigned int __nmi_count; /* arch dependent */
unsigned int apic_timer_irqs; /* arch dependent */
diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h
index 14b1fa1ebef8..938fc1364344 100644
--- a/include/asm-i386/mmu_context.h
+++ b/include/asm-i386/mmu_context.h
@@ -14,16 +14,21 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
void destroy_context(struct mm_struct *mm);
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
#ifdef CONFIG_SMP
+ unsigned cpu = smp_processor_id();
if (cpu_tlbstate[cpu].state == TLBSTATE_OK)
cpu_tlbstate[cpu].state = TLBSTATE_LAZY;
#endif
}
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev,
+ struct mm_struct *next,
+ struct task_struct *tsk)
{
+ int cpu = smp_processor_id();
+
if (likely(prev != next)) {
/* stop flush ipis for the previous mm */
clear_bit(cpu, &prev->cpu_vm_mask);
@@ -62,6 +67,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str
asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0))
#define activate_mm(prev, next) \
- switch_mm((prev),(next),NULL,smp_processor_id())
+ switch_mm((prev),(next),NULL)
#endif
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index b6138f07c309..d5da17912a8c 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -32,8 +32,7 @@ extern struct pglist_data *node_data[];
#define alloc_bootmem_low_pages_node(ignore, x) \
__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-#define node_size(nid) (node_data[nid]->node_size)
-#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
+#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
/*
* Following are macros that each numa implmentation must define.
@@ -54,7 +53,7 @@ extern struct pglist_data *node_data[];
#define node_end_pfn(nid) \
({ \
pg_data_t *__pgdat = NODE_DATA(nid); \
- __pgdat->node_start_pfn + __pgdat->node_size; \
+ __pgdat->node_start_pfn + __pgdat->node_spanned_pages; \
})
#define local_mapnr(kvaddr) \
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index 005ce2e61748..cfcfb5b7a128 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -21,8 +21,21 @@ struct timer_opts{
#define TICK_SIZE (tick_nsec / 1000)
extern struct timer_opts* select_timer(void);
+extern void clock_fallback(void);
/* Modifiers for buggy PIT handling */
extern int pit_latch_buggy;
+
+extern struct timer_opts *cur_timer;
+extern int timer_ack;
+
+/* list of externed timers */
+extern struct timer_opts timer_none;
+extern struct timer_opts timer_pit;
+extern struct timer_opts timer_tsc;
+#ifdef CONFIG_X86_CYCLONE_TIMER
+extern struct timer_opts timer_cyclone;
+#endif
+
#endif
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index b1bdc016eed5..f39e505e3eb4 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -275,8 +275,9 @@
#define __NR_clock_nanosleep (__NR_timer_create+8)
#define __NR_statfs64 268
#define __NR_fstatfs64 269
+#define __NR_tgkill 270
-#define NR_syscalls 270
+#define NR_syscalls 271
/* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
diff --git a/include/asm-ia64/div64.h b/include/asm-ia64/div64.h
index 08c03f672041..6cd978cefb28 100644
--- a/include/asm-ia64/div64.h
+++ b/include/asm-ia64/div64.h
@@ -1,20 +1 @@
-#ifndef _ASM_IA64_DIV64_H
-#define _ASM_IA64_DIV64_H
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64...
- */
-
-#define do_div(n,base) \
-({ \
- int _res; \
- _res = ((unsigned long) (n)) % (unsigned) (base); \
- (n) = ((unsigned long) (n)) / (unsigned) (base); \
- _res; \
-})
-
-#endif /* _ASM_IA64_DIV64_H */
+#include <asm-generic/div64.h>
diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
index a614a1dbbb61..dee1cd007f5a 100644
--- a/include/asm-ia64/mmu_context.h
+++ b/include/asm-ia64/mmu_context.h
@@ -71,7 +71,7 @@ DECLARE_PER_CPU(u8, ia64_need_tlb_flush);
extern void wrap_mmu_context (struct mm_struct *mm);
static inline void
-enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb (struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -198,7 +198,7 @@ activate_mm (struct mm_struct *prev, struct mm_struct *next)
activate_context(next);
}
-#define switch_mm(prev_mm,next_mm,next_task,cpu) activate_mm(prev_mm, next_mm)
+#define switch_mm(prev_mm,next_mm,next_task) activate_mm(prev_mm, next_mm)
# endif /* ! __ASSEMBLY__ */
#endif /* _ASM_IA64_MMU_CONTEXT_H */
diff --git a/include/asm-m68k/div64.h b/include/asm-m68k/div64.h
index 16bf1f88d40c..9f65de1a2480 100644
--- a/include/asm-m68k/div64.h
+++ b/include/asm-m68k/div64.h
@@ -3,7 +3,6 @@
/* n = n / base; return rem; */
-#if 1
#define do_div(n, base) ({ \
union { \
unsigned long n32[2]; \
@@ -23,13 +22,5 @@
(n) = __n.n64; \
__rem; \
})
-#else
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; \
-})
-#endif
#endif /* _M68K_DIV64_H */
diff --git a/include/asm-m68k/mmu_context.h b/include/asm-m68k/mmu_context.h
index 04cfa101eb70..4983fb7b6a0c 100644
--- a/include/asm-m68k/mmu_context.h
+++ b/include/asm-m68k/mmu_context.h
@@ -3,7 +3,7 @@
#include <linux/config.h>
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -79,7 +79,7 @@ extern inline void switch_mm_0460(struct mm_struct *mm)
asm volatile (".chip 68k");
}
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
if (prev != next) {
if (CPU_IS_020_OR_030)
@@ -137,7 +137,7 @@ static inline void activate_context(struct mm_struct *mm)
sun3_put_context(mm->context);
}
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
activate_context(tsk->mm);
}
diff --git a/include/asm-m68knommu/div64.h b/include/asm-m68knommu/div64.h
index b41200162d8b..6cd978cefb28 100644
--- a/include/asm-m68knommu/div64.h
+++ b/include/asm-m68knommu/div64.h
@@ -1,13 +1 @@
-#ifndef _M68KNOMMU_DIV64_H
-#define _M68KNOMMU_DIV64_H
-
-/* n = n / base; return rem; */
-
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; \
-})
-
-#endif /* _M68K_DIV64_H */
+#include <asm-generic/div64.h>
diff --git a/include/asm-m68knommu/flat.h b/include/asm-m68knommu/flat.h
index fe805aaa33df..73712f276cc0 100644
--- a/include/asm-m68knommu/flat.h
+++ b/include/asm-m68knommu/flat.h
@@ -5,6 +5,12 @@
#ifndef __M68KNOMMU_FLAT_H__
#define __M68KNOMMU_FLAT_H__
-#define flat_argvp_envp_on_stack() 1
+#define flat_stack_align(sp) /* nothing needed */
+#define flat_argvp_envp_on_stack() 1
+#define flat_old_ram_flag(flags) (flags)
+#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
+#define flat_get_addr_from_rp(rp, relval) get_unaligned(rp)
+#define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp)
+#define flat_get_relocate_addr(rel) (rel)
#endif /* __M68KNOMMU_FLAT_H__ */
diff --git a/include/asm-m68knommu/io.h b/include/asm-m68knommu/io.h
index d0dbd4c796c4..f42645e4a2d2 100644
--- a/include/asm-m68knommu/io.h
+++ b/include/asm-m68knommu/io.h
@@ -43,6 +43,13 @@ static inline unsigned int _swapl(volatile unsigned long v)
#define writew(b,addr) (void)((*(volatile unsigned short *) (addr)) = (b))
#define writel(b,addr) (void)((*(volatile unsigned int *) (addr)) = (b))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
static inline void io_outsb(unsigned int addr, void *buf, int len)
{
volatile unsigned char *ap = (volatile unsigned char *) addr;
@@ -100,7 +107,7 @@ static inline void io_insl(unsigned int addr, void *buf, int len)
#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
-#define inb(addr) readb(addr)
+#define inb(addr) readb(addr)
#define inw(addr) readw(addr)
#define inl(addr) readl(addr)
#define outb(x,addr) ((void) writeb(x,addr))
diff --git a/include/asm-m68knommu/mmu_context.h b/include/asm-m68knommu/mmu_context.h
index a4286176513c..9bc0fd49b8aa 100644
--- a/include/asm-m68knommu/mmu_context.h
+++ b/include/asm-m68knommu/mmu_context.h
@@ -6,7 +6,7 @@
#include <asm/page.h>
#include <asm/pgalloc.h>
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -19,7 +19,7 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
#define destroy_context(mm) do { } while(0)
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
}
diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h
index 7defa6391f0b..0d063a97f1c7 100644
--- a/include/asm-m68knommu/page.h
+++ b/include/asm-m68knommu/page.h
@@ -6,7 +6,7 @@
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT (12)
-#define PAGE_SIZE (4096)
+#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#ifdef __KERNEL__
diff --git a/include/asm-m68knommu/semaphore.h b/include/asm-m68knommu/semaphore.h
index f6cfb9f49001..4720a09e6191 100644
--- a/include/asm-m68knommu/semaphore.h
+++ b/include/asm-m68knommu/semaphore.h
@@ -145,7 +145,7 @@ extern inline int down_trylock(struct semaphore * sem)
".previous"
: "=d" (result)
: "a" (sem1)
- : "%d0", "memory");
+ : "memory");
return result;
}
diff --git a/include/asm-m68knommu/uaccess.h b/include/asm-m68knommu/uaccess.h
index 6ff1747b02e0..9f890ed45b4f 100644
--- a/include/asm-m68knommu/uaccess.h
+++ b/include/asm-m68knommu/uaccess.h
@@ -13,21 +13,14 @@
#define VERIFY_READ 0
#define VERIFY_WRITE 1
-/* We let the MMU do all checking */
-extern inline int access_ok(int type, const void * addr, unsigned long size)
+#define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
+
+static inline int _access_ok(unsigned long addr, unsigned long size)
{
-#define RANGE_CHECK_OK(addr, size, lower, upper) \
- (((addr) >= (lower)) && (((addr) + (size)) < (upper)))
-
-#ifdef CONFIG_COLDFIRE
- extern unsigned long _ramend;
- return(RANGE_CHECK_OK((unsigned long) addr, size, 0L, _ramend) ||
- (is_in_rom((unsigned long) addr) &&
- is_in_rom((unsigned long) addr + size)));
-#else
- /* DAVIDM - this could be restricted a lot more */
- return(RANGE_CHECK_OK((unsigned long)addr, size, 0, 0x10f00000));
-#endif
+ extern unsigned long memory_start, memory_end;
+
+ return (((addr >= memory_start) && (addr+size < memory_end)) ||
+ (is_in_rom(addr) && is_in_rom(addr+size)));
}
extern inline int verify_area(int type, const void * addr, unsigned long size)
diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h
index cf19cd768f95..8d2153f323ef 100644
--- a/include/asm-mips/mmu_context.h
+++ b/include/asm-mips/mmu_context.h
@@ -49,7 +49,7 @@ extern unsigned long pgd_current[];
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -92,9 +92,10 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm)
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
unsigned long flags;
+ unsigned cpu = smp_processor_id();
local_irq_save(flags);
diff --git a/include/asm-mips64/div64.h b/include/asm-mips64/div64.h
index 3ec1fadcfd7e..1147123d4d82 100644
--- a/include/asm-mips64/div64.h
+++ b/include/asm-mips64/div64.h
@@ -27,23 +27,6 @@
(res) = __quot; \
__mod; })
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n, base) ({ \
- unsigned long __quot; \
- unsigned int __mod; \
- unsigned long __div; \
- unsigned int __base; \
- \
- __div = (n); \
- __base = (base); \
- \
- __mod = __div % __base; \
- __quot = __div / __base; \
- \
- (n) = __quot; \
- __mod; })
+#include <asm-generic.h>
#endif /* _ASM_DIV64_H */
diff --git a/include/asm-mips64/mmu_context.h b/include/asm-mips64/mmu_context.h
index 107e2459ccd0..b7ca8c085452 100644
--- a/include/asm-mips64/mmu_context.h
+++ b/include/asm-mips64/mmu_context.h
@@ -40,7 +40,7 @@ extern unsigned long pgd_current[];
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
#define asid_cache(cpu) (cpu_data[cpu].asid_cache)
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
diff --git a/include/asm-mips64/mmzone.h b/include/asm-mips64/mmzone.h
index 25a42752b182..cba337b07be1 100644
--- a/include/asm-mips64/mmzone.h
+++ b/include/asm-mips64/mmzone.h
@@ -24,7 +24,7 @@ extern plat_pg_data_t *plat_node_data[];
#define PHYSADDR_TO_NID(pa) NASID_TO_COMPACT_NODEID(NASID_GET(pa))
#define PLAT_NODE_DATA(n) (plat_node_data[n])
-#define PLAT_NODE_DATA_SIZE(n) (PLAT_NODE_DATA(n)->gendata.node_size)
+#define PLAT_NODE_DATA_SIZE(n) (PLAT_NODE_DATA(n)->gendata.node_spanned_pages)
#define PLAT_NODE_DATA_LOCALNR(p, n) \
(((p) >> PAGE_SHIFT) - PLAT_NODE_DATA(n)->gendata.node_start_pfn)
diff --git a/include/asm-parisc/div64.h b/include/asm-parisc/div64.h
index e86e35e8a272..6cd978cefb28 100644
--- a/include/asm-parisc/div64.h
+++ b/include/asm-parisc/div64.h
@@ -1,54 +1 @@
-#ifndef __ASM_PARISC_DIV64
-#define __ASM_PARISC_DIV64
-
-#ifdef __LP64__
-
-/*
- * Copyright (C) 1999 Hewlett-Packard Co
- * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
- *
- * vsprintf uses this to divide a 64-bit integer N by a small integer BASE.
- * This is incredibly hard on IA-64 and HPPA
- */
-
-#define do_div(n,base) \
-({ \
- int _res; \
- _res = ((unsigned long) (n)) % (unsigned) (base); \
- (n) = ((unsigned long) (n)) / (unsigned) (base); \
- _res; \
-})
-
-#else
-/*
- * unsigned long long division. Yuck Yuck! What is Linux coming to?
- * This is 100% disgusting
- */
-#define do_div(n,base) \
-({ \
- unsigned long __low, __low2, __high, __rem; \
- __low = (n) & 0xffffffff; \
- __high = (n) >> 32; \
- if (__high) { \
- __rem = __high % (unsigned long)base; \
- __high = __high / (unsigned long)base; \
- __low2 = __low >> 16; \
- __low2 += __rem << 16; \
- __rem = __low2 % (unsigned long)base; \
- __low2 = __low2 / (unsigned long)base; \
- __low = __low & 0xffff; \
- __low += __rem << 16; \
- __rem = __low % (unsigned long)base; \
- __low = __low / (unsigned long)base; \
- n = __low + ((long long)__low2 << 16) + \
- ((long long) __high << 32); \
- } else { \
- __rem = __low % (unsigned long)base; \
- n = (__low / (unsigned long)base); \
- } \
- __rem; \
-})
-#endif
-
-#endif
-
+#include <asm-generic/div64.h>
diff --git a/include/asm-parisc/mmu_context.h b/include/asm-parisc/mmu_context.h
index 1ff9e5f0582c..6327156282f2 100644
--- a/include/asm-parisc/mmu_context.h
+++ b/include/asm-parisc/mmu_context.h
@@ -6,7 +6,7 @@
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -43,7 +43,7 @@ static inline void load_context(mm_context_t context)
#endif
}
-static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
{
if (prev != next) {
@@ -69,6 +69,6 @@ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
if (next->context == 0)
next->context = alloc_sid();
- switch_mm(prev,next,current,0);
+ switch_mm(prev,next,current);
}
#endif
diff --git a/include/asm-ppc/div64.h b/include/asm-ppc/div64.h
index ec3ae5bcb3de..6cd978cefb28 100644
--- a/include/asm-ppc/div64.h
+++ b/include/asm-ppc/div64.h
@@ -1,23 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-#include <linux/types.h>
-
-extern u32 __div64_32(u64 *dividend, u32 div);
-
-#define do_div(n, div) ({ \
- u64 __n = (n); \
- u32 __d = (div); \
- u32 __q, __r; \
- if ((__n >> 32) == 0) { \
- __q = (u32)__n / __d; \
- __r = (u32)__n - __q * __d; \
- (n) = __q; \
- } else { \
- __r = __div64_32(&__n, __d); \
- (n) = __n; \
- } \
- __r; \
-})
-
-#endif
+#include <asm-generic/div64.h>
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index 131269863309..1e8176b2d122 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -48,7 +48,7 @@
-- Dan
*/
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -153,7 +153,7 @@ static inline void destroy_context(struct mm_struct *mm)
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, int cpu)
+ struct task_struct *tsk)
{
tsk->thread.pgdir = next->pgd;
get_mmu_context(next);
diff --git a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
index 887fa5302a9f..5d121448d3c1 100644
--- a/include/asm-ppc/serial.h
+++ b/include/asm-ppc/serial.h
@@ -25,11 +25,9 @@
#elif defined(CONFIG_PRPMC800)
#include <platforms/prpmc800_serial.h>
#elif defined(CONFIG_SANDPOINT)
-#include <platforms/sandpoint_serial.h>
+#include <platforms/sandpoint.h>
#elif defined(CONFIG_SPRUCE)
#include <platforms/spruce_serial.h>
-#elif defined(CONFIG_ZX4500)
-#include <platforms/zx4500_serial.h>
#elif defined(CONFIG_40x)
#include <asm/ibm4xx.h>
#else
diff --git a/include/asm-ppc64/div64.h b/include/asm-ppc64/div64.h
index 22ba87033456..6cd978cefb28 100644
--- a/include/asm-ppc64/div64.h
+++ b/include/asm-ppc64/div64.h
@@ -1,18 +1 @@
-#ifndef __PPC_DIV64
-#define __PPC_DIV64
-
-/* Copyright 2001 PPC64 Team, IBM Corp
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) (n)) % (unsigned) (base); \
- (n) = ((unsigned long) (n)) / (unsigned) (base); \
- __res; })
-
-#endif
+#include <asm-generic/div64.h>
diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
index 1014f086e5e7..a84ee5812e9f 100644
--- a/include/asm-ppc64/mmu_context.h
+++ b/include/asm-ppc64/mmu_context.h
@@ -56,7 +56,7 @@ struct mmu_context_queue_t {
extern struct mmu_context_queue_t mmu_context_queue;
static inline void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -140,10 +140,10 @@ extern void flush_stab(struct task_struct *tsk, struct mm_struct *mm);
*/
static inline void
switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, int cpu)
+ struct task_struct *tsk)
{
flush_stab(tsk, next);
- set_bit(cpu, &next->cpu_vm_mask);
+ set_bit(smp_processor_id(), &next->cpu_vm_mask);
}
#define deactivate_mm(tsk,mm) do { } while (0)
@@ -153,7 +153,7 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
* the context for the new mm so we see the new mappings.
*/
#define activate_mm(active_mm, mm) \
- switch_mm(active_mm, mm, current, smp_processor_id());
+ switch_mm(active_mm, mm, current);
#define VSID_RANDOMIZER 42470972311
#define VSID_MASK 0xfffffffff
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index 8503e25b17b3..2e5136012845 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -54,7 +54,6 @@ static inline int pa_to_nid(unsigned long pa)
*/
#define NODE_DATA(nid) (&node_data[nid])
-#define node_size(nid) (NODE_DATA(nid)->node_size)
#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
/*
diff --git a/include/asm-s390/div64.h b/include/asm-s390/div64.h
index 79b5f06fa174..0c5f739832f1 100644
--- a/include/asm-s390/div64.h
+++ b/include/asm-s390/div64.h
@@ -43,13 +43,7 @@
})
#else /* __s390x__ */
-
-#define do_div(n,base) ({ \
-int __res; \
-__res = ((unsigned long) n) % (unsigned) base; \
-n = ((unsigned long) n) / (unsigned) base; \
-__res; })
-
+#include <asm-generic/div64.h>
#endif /* __s390x__ */
#endif
diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h
index 87be0aab7028..0e63fd521893 100644
--- a/include/asm-s390/mmu_context.h
+++ b/include/asm-s390/mmu_context.h
@@ -17,12 +17,12 @@
#define destroy_context(mm) flush_tlb_mm(mm)
static inline void enter_lazy_tlb(struct mm_struct *mm,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
}
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
unsigned long pgd;
@@ -42,7 +42,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
: : "m" (pgd) );
#endif /* __s390x__ */
}
- set_bit(cpu, &next->cpu_vm_mask);
+ set_bit(smp_processor_id(), &next->cpu_vm_mask);
}
#define deactivate_mm(tsk,mm) do { } while (0)
@@ -50,7 +50,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
extern inline void activate_mm(struct mm_struct *prev,
struct mm_struct *next)
{
- switch_mm(prev, next, current, smp_processor_id());
+ switch_mm(prev, next, current);
}
#endif
diff --git a/include/asm-sh/div64.h b/include/asm-sh/div64.h
index dd4665af4fb8..6cd978cefb28 100644
--- a/include/asm-sh/div64.h
+++ b/include/asm-sh/div64.h
@@ -1,20 +1 @@
-#ifndef __ASM_SH_DIV64
-#define __ASM_SH_DIV64
-
-extern u64 __div64_32(u64 n, u32 d);
-
-#define do_div(n,base) ({ \
-u64 __n = (n), __q; \
-u32 __base = (base); \
-u32 __res; \
-if ((__n >> 32) == 0) { \
- __res = ((unsigned long) __n) % (unsigned) __base; \
- (n) = ((unsigned long) __n) / (unsigned) __base; \
-} else { \
- __q = __div64_32(__n, __base); \
- __res = __n - __q * __base; \
- (n) = __q; \
-} \
-__res; })
-
-#endif /* __ASM_SH_DIV64 */
+#include <asm-generic/div64.h>
diff --git a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h
index 17775400498b..c956ddea556b 100644
--- a/include/asm-sh/mmu_context.h
+++ b/include/asm-sh/mmu_context.h
@@ -129,7 +129,7 @@ static __inline__ void activate_context(struct mm_struct *mm)
(Currently not used) */
static __inline__ void switch_mm(struct mm_struct *prev,
struct mm_struct *next,
- struct task_struct *tsk, unsigned int cpu)
+ struct task_struct *tsk)
{
if (likely(prev != next)) {
unsigned long __pgdir = (unsigned long)next->pgd;
@@ -144,10 +144,10 @@ static __inline__ void switch_mm(struct mm_struct *prev,
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev, next) \
- switch_mm((prev),(next),NULL,smp_processor_id())
+ switch_mm((prev),(next),NULL)
static __inline__ void
-enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
#else /* !CONFIG_MMU */
@@ -157,10 +157,10 @@ enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
#define set_asid(asid) do { } while (0)
#define get_asid() (0)
#define activate_context(mm) do { } while (0)
-#define switch_mm(prev,next,tsk,cpu) do { } while (0)
+#define switch_mm(prev,next,tsk) do { } while (0)
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) do { } while (0)
-#define enter_lazy_tlb(mm,tsk,cpu) do { } while (0)
+#define enter_lazy_tlb(mm,tsk) do { } while (0)
#endif /* CONFIG_MMU */
#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4)
diff --git a/include/asm-sparc/div64.h b/include/asm-sparc/div64.h
index 167260a9c953..6cd978cefb28 100644
--- a/include/asm-sparc/div64.h
+++ b/include/asm-sparc/div64.h
@@ -1,11 +1 @@
-#ifndef __SPARC_DIV64
-#define __SPARC_DIV64
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; })
-
-#endif /* __SPARC_DIV64 */
+#include <asm-generic/div64.h>
diff --git a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h
index f386a8f4bbe8..ed1e01d04d21 100644
--- a/include/asm-sparc/mmu_context.h
+++ b/include/asm-sparc/mmu_context.h
@@ -5,7 +5,7 @@
#ifndef __ASSEMBLY__
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -26,14 +26,14 @@ BTFIXUPDEF_CALL(void, destroy_context, struct mm_struct *)
#define destroy_context(mm) BTFIXUP_CALL(destroy_context)(mm)
/* Switch the current MM context. */
-BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *, int)
+BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct task_struct *)
-#define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu)
+#define switch_mm(old_mm, mm, tsk) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk)
#define deactivate_mm(tsk,mm) do { } while (0)
/* Activate a new MM instance for the current task. */
-#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id())
+#define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL)
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/div64.h b/include/asm-sparc64/div64.h
index a36d2443d209..6cd978cefb28 100644
--- a/include/asm-sparc64/div64.h
+++ b/include/asm-sparc64/div64.h
@@ -1,14 +1 @@
-#ifndef __SPARC64_DIV64
-#define __SPARC64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; })
-
-#endif /* __SPARC64_DIV64 */
+#include <asm-generic/div64.h>
diff --git a/include/asm-sparc64/hardirq.h b/include/asm-sparc64/hardirq.h
index 44a4e97f4793..97e43a160b3b 100644
--- a/include/asm-sparc64/hardirq.h
+++ b/include/asm-sparc64/hardirq.h
@@ -11,15 +11,9 @@
#include <linux/spinlock.h>
#include <linux/cache.h>
-/* entry.S is sensitive to the offsets of these fields */
-/* rtrap.S is sensitive to the size of this structure */
+/* rtrap.S is sensitive to the offsets of these fields */
typedef struct {
unsigned int __softirq_pending;
- unsigned int __unused_1;
- unsigned int __unused_2;
- unsigned int __unused_3;
- unsigned int __syscall_count;
- struct task_struct * __ksoftirqd_task;
} ____cacheline_aligned irq_cpustat_t;
#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h
index ab9eedf22860..292757aa3176 100644
--- a/include/asm-sparc64/mmu_context.h
+++ b/include/asm-sparc64/mmu_context.h
@@ -27,7 +27,7 @@
#include <asm/system.h>
#include <asm/spitfire.h>
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
@@ -106,7 +106,7 @@ do { \
extern void __flush_tlb_mm(unsigned long, unsigned long);
/* Switch the current MM context. */
-static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
+static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk)
{
unsigned long ctx_valid;
@@ -125,7 +125,7 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str
}
{
- unsigned long vm_mask = (1UL << cpu);
+ unsigned long vm_mask = (1UL << smp_processor_id());
/* Even if (mm == old_mm) we _must_ check
* the cpu_vm_mask. If we do not we could
diff --git a/include/asm-sparc64/xor.h b/include/asm-sparc64/xor.h
index 9ecc98f667d0..8b3a7e4b6062 100644
--- a/include/asm-sparc64/xor.h
+++ b/include/asm-sparc64/xor.h
@@ -16,15 +16,6 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/*
- * Requirements:
- * !(((long)dest | (long)sourceN) & (64 - 1)) &&
- * !(len & 127) && len >= 256
- *
- * It is done in pure assembly, as otherwise gcc makes it a non-leaf
- * function, which is not what we want.
- */
-
#include <asm/pstate.h>
#include <asm/asi.h>
@@ -36,356 +27,7 @@ extern void xor_vis_4(unsigned long, unsigned long *, unsigned long *,
extern void xor_vis_5(unsigned long, unsigned long *, unsigned long *,
unsigned long *, unsigned long *, unsigned long *);
-#define _S(x) __S(x)
-#define __S(x) #x
-#define DEF(x) __asm__(#x " = " _S(x))
-
-DEF(FPRS_FEF);
-DEF(FPRS_DU);
-DEF(ASI_BLK_P);
-
-/* ??? We set and use %asi instead of using ASI_BLK_P directly because gas
- currently does not accept symbolic constants for the ASI specifier. */
-
-__asm__ ("
- .text
- .globl xor_vis_2
- .type xor_vis_2,@function
-xor_vis_2:
- rd %fprs, %o5
- andcc %o5, FPRS_FEF|FPRS_DU, %g0
- be,pt %icc, 0f
- sethi %hi(VISenter), %g1
- jmpl %g1 + %lo(VISenter), %g7
- add %g7, 8, %g7
-0: wr %g0, FPRS_FEF, %fprs
- rd %asi, %g1
- wr %g0, ASI_BLK_P, %asi
- membar #LoadStore|#StoreLoad|#StoreStore
- sub %o0, 128, %o0
- ldda [%o1] %asi, %f0
- ldda [%o2] %asi, %f16
-
-2: ldda [%o1 + 64] %asi, %f32
- fxor %f0, %f16, %f16
- fxor %f2, %f18, %f18
- fxor %f4, %f20, %f20
- fxor %f6, %f22, %f22
- fxor %f8, %f24, %f24
- fxor %f10, %f26, %f26
- fxor %f12, %f28, %f28
- fxor %f14, %f30, %f30
- stda %f16, [%o1] %asi
- ldda [%o2 + 64] %asi, %f48
- ldda [%o1 + 128] %asi, %f0
- fxor %f32, %f48, %f48
- fxor %f34, %f50, %f50
- add %o1, 128, %o1
- fxor %f36, %f52, %f52
- add %o2, 128, %o2
- fxor %f38, %f54, %f54
- subcc %o0, 128, %o0
- fxor %f40, %f56, %f56
- fxor %f42, %f58, %f58
- fxor %f44, %f60, %f60
- fxor %f46, %f62, %f62
- stda %f48, [%o1 - 64] %asi
- bne,pt %xcc, 2b
- ldda [%o2] %asi, %f16
-
- ldda [%o1 + 64] %asi, %f32
- fxor %f0, %f16, %f16
- fxor %f2, %f18, %f18
- fxor %f4, %f20, %f20
- fxor %f6, %f22, %f22
- fxor %f8, %f24, %f24
- fxor %f10, %f26, %f26
- fxor %f12, %f28, %f28
- fxor %f14, %f30, %f30
- stda %f16, [%o1] %asi
- ldda [%o2 + 64] %asi, %f48
- membar #Sync
- fxor %f32, %f48, %f48
- fxor %f34, %f50, %f50
- fxor %f36, %f52, %f52
- fxor %f38, %f54, %f54
- fxor %f40, %f56, %f56
- fxor %f42, %f58, %f58
- fxor %f44, %f60, %f60
- fxor %f46, %f62, %f62
- stda %f48, [%o1 + 64] %asi
- membar #Sync|#StoreStore|#StoreLoad
- wr %g1, %g0, %asi
- retl
- wr %g0, 0, %fprs
- .size xor_vis_2, .-xor_vis_2
-
-
- .globl xor_vis_3
- .type xor_vis_3,@function
-xor_vis_3:
- rd %fprs, %o5
- andcc %o5, FPRS_FEF|FPRS_DU, %g0
- be,pt %icc, 0f
- sethi %hi(VISenter), %g1
- jmpl %g1 + %lo(VISenter), %g7
- add %g7, 8, %g7
-0: wr %g0, FPRS_FEF, %fprs
- rd %asi, %g1
- wr %g0, ASI_BLK_P, %asi
- membar #LoadStore|#StoreLoad|#StoreStore
- sub %o0, 64, %o0
- ldda [%o1] %asi, %f0
- ldda [%o2] %asi, %f16
-
-3: ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f48
- fxor %f2, %f18, %f50
- add %o1, 64, %o1
- fxor %f4, %f20, %f52
- fxor %f6, %f22, %f54
- add %o2, 64, %o2
- fxor %f8, %f24, %f56
- fxor %f10, %f26, %f58
- fxor %f12, %f28, %f60
- fxor %f14, %f30, %f62
- ldda [%o1] %asi, %f0
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- add %o3, 64, %o3
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- subcc %o0, 64, %o0
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- stda %f48, [%o1 - 64] %asi
- bne,pt %xcc, 3b
- ldda [%o2] %asi, %f16
-
- ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f48
- fxor %f2, %f18, %f50
- fxor %f4, %f20, %f52
- fxor %f6, %f22, %f54
- fxor %f8, %f24, %f56
- fxor %f10, %f26, %f58
- fxor %f12, %f28, %f60
- fxor %f14, %f30, %f62
- membar #Sync
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- stda %f48, [%o1] %asi
- membar #Sync|#StoreStore|#StoreLoad
- wr %g1, %g0, %asi
- retl
- wr %g0, 0, %fprs
- .size xor_vis_3, .-xor_vis_3
-
-
- .globl xor_vis_4
- .type xor_vis_4,@function
-xor_vis_4:
- rd %fprs, %o5
- andcc %o5, FPRS_FEF|FPRS_DU, %g0
- be,pt %icc, 0f
- sethi %hi(VISenter), %g1
- jmpl %g1 + %lo(VISenter), %g7
- add %g7, 8, %g7
-0: wr %g0, FPRS_FEF, %fprs
- rd %asi, %g1
- wr %g0, ASI_BLK_P, %asi
- membar #LoadStore|#StoreLoad|#StoreStore
- sub %o0, 64, %o0
- ldda [%o1] %asi, %f0
- ldda [%o2] %asi, %f16
-
-4: ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f16
- fxor %f2, %f18, %f18
- add %o1, 64, %o1
- fxor %f4, %f20, %f20
- fxor %f6, %f22, %f22
- add %o2, 64, %o2
- fxor %f8, %f24, %f24
- fxor %f10, %f26, %f26
- fxor %f12, %f28, %f28
- fxor %f14, %f30, %f30
- ldda [%o4] %asi, %f48
- fxor %f16, %f32, %f32
- fxor %f18, %f34, %f34
- fxor %f20, %f36, %f36
- fxor %f22, %f38, %f38
- add %o3, 64, %o3
- fxor %f24, %f40, %f40
- fxor %f26, %f42, %f42
- fxor %f28, %f44, %f44
- fxor %f30, %f46, %f46
- ldda [%o1] %asi, %f0
- fxor %f32, %f48, %f48
- fxor %f34, %f50, %f50
- fxor %f36, %f52, %f52
- add %o4, 64, %o4
- fxor %f38, %f54, %f54
- fxor %f40, %f56, %f56
- fxor %f42, %f58, %f58
- subcc %o0, 64, %o0
- fxor %f44, %f60, %f60
- fxor %f46, %f62, %f62
- stda %f48, [%o1 - 64] %asi
- bne,pt %xcc, 4b
- ldda [%o2] %asi, %f16
-
- ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f16
- fxor %f2, %f18, %f18
- fxor %f4, %f20, %f20
- fxor %f6, %f22, %f22
- fxor %f8, %f24, %f24
- fxor %f10, %f26, %f26
- fxor %f12, %f28, %f28
- fxor %f14, %f30, %f30
- ldda [%o4] %asi, %f48
- fxor %f16, %f32, %f32
- fxor %f18, %f34, %f34
- fxor %f20, %f36, %f36
- fxor %f22, %f38, %f38
- fxor %f24, %f40, %f40
- fxor %f26, %f42, %f42
- fxor %f28, %f44, %f44
- fxor %f30, %f46, %f46
- membar #Sync
- fxor %f32, %f48, %f48
- fxor %f34, %f50, %f50
- fxor %f36, %f52, %f52
- fxor %f38, %f54, %f54
- fxor %f40, %f56, %f56
- fxor %f42, %f58, %f58
- fxor %f44, %f60, %f60
- fxor %f46, %f62, %f62
- stda %f48, [%o1] %asi
- membar #Sync|#StoreStore|#StoreLoad
- wr %g1, %g0, %asi
- retl
- wr %g0, 0, %fprs
- .size xor_vis_4, .-xor_vis_4
-
-
- .globl xor_vis_5
- .type xor_vis_5,@function
-xor_vis_5:
- mov %o5, %g5
- rd %fprs, %o5
- andcc %o5, FPRS_FEF|FPRS_DU, %g0
- be,pt %icc, 0f
- sethi %hi(VISenter), %g1
- jmpl %g1 + %lo(VISenter), %g7
- add %g7, 8, %g7
-0: wr %g0, FPRS_FEF, %fprs
- mov %g5, %o5
- rd %asi, %g1
- wr %g0, ASI_BLK_P, %asi
- membar #LoadStore|#StoreLoad|#StoreStore
- sub %o0, 64, %o0
- ldda [%o1] %asi, %f0
- ldda [%o2] %asi, %f16
-
-5: ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f48
- fxor %f2, %f18, %f50
- add %o1, 64, %o1
- fxor %f4, %f20, %f52
- fxor %f6, %f22, %f54
- add %o2, 64, %o2
- fxor %f8, %f24, %f56
- fxor %f10, %f26, %f58
- fxor %f12, %f28, %f60
- fxor %f14, %f30, %f62
- ldda [%o4] %asi, %f16
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- add %o3, 64, %o3
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- ldda [%o5] %asi, %f32
- fxor %f48, %f16, %f48
- fxor %f50, %f18, %f50
- add %o4, 64, %o4
- fxor %f52, %f20, %f52
- fxor %f54, %f22, %f54
- add %o5, 64, %o5
- fxor %f56, %f24, %f56
- fxor %f58, %f26, %f58
- fxor %f60, %f28, %f60
- fxor %f62, %f30, %f62
- ldda [%o1] %asi, %f0
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- subcc %o0, 64, %o0
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- stda %f48, [%o1 - 64] %asi
- bne,pt %xcc, 5b
- ldda [%o2] %asi, %f16
-
- ldda [%o3] %asi, %f32
- fxor %f0, %f16, %f48
- fxor %f2, %f18, %f50
- fxor %f4, %f20, %f52
- fxor %f6, %f22, %f54
- fxor %f8, %f24, %f56
- fxor %f10, %f26, %f58
- fxor %f12, %f28, %f60
- fxor %f14, %f30, %f62
- ldda [%o4] %asi, %f16
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- ldda [%o5] %asi, %f32
- fxor %f48, %f16, %f48
- fxor %f50, %f18, %f50
- fxor %f52, %f20, %f52
- fxor %f54, %f22, %f54
- fxor %f56, %f24, %f56
- fxor %f58, %f26, %f58
- fxor %f60, %f28, %f60
- fxor %f62, %f30, %f62
- membar #Sync
- fxor %f48, %f32, %f48
- fxor %f50, %f34, %f50
- fxor %f52, %f36, %f52
- fxor %f54, %f38, %f54
- fxor %f56, %f40, %f56
- fxor %f58, %f42, %f58
- fxor %f60, %f44, %f60
- fxor %f62, %f46, %f62
- stda %f48, [%o1] %asi
- membar #Sync|#StoreStore|#StoreLoad
- wr %g1, %g0, %asi
- retl
- wr %g0, 0, %fprs
- .size xor_vis_5, .-xor_vis_5
-");
+/* XXX Ugh, write cheetah versions... -DaveM */
static struct xor_block_template xor_block_VIS = {
.name = "VIS",
diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
index 14ca8b2a4628..4ddffc1a7832 100644
--- a/include/asm-um/mmu_context.h
+++ b/include/asm-um/mmu_context.h
@@ -21,8 +21,10 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
extern void switch_mm_skas(int mm_fd);
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
+ unsigned cpu = smp_processor_id();
+
if(prev != next){
clear_bit(cpu, &prev->cpu_vm_mask);
set_bit(cpu, &next->cpu_vm_mask);
@@ -33,7 +35,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
}
static inline void enter_lazy_tlb(struct mm_struct *mm,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
}
diff --git a/include/asm-v850/div64.h b/include/asm-v850/div64.h
index 165518b4623c..6cd978cefb28 100644
--- a/include/asm-v850/div64.h
+++ b/include/asm-v850/div64.h
@@ -1,11 +1 @@
-#ifndef __V850_DIV64_H__
-#define __V850_DIV64_H__
-
-/* We're not 64-bit, but... */
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) n) % (unsigned) base; \
- n = ((unsigned long) n) / (unsigned) base; \
- __res; })
-
-#endif /* __V850_DIV64_H__ */
+#include <asm-generic/div64.h>
diff --git a/include/asm-v850/flat.h b/include/asm-v850/flat.h
index 94a42a41e843..17106c894ab7 100644
--- a/include/asm-v850/flat.h
+++ b/include/asm-v850/flat.h
@@ -1,8 +1,8 @@
/*
* include/asm-v850/flat.h -- uClinux flat-format executables
*
- * Copyright (C) 2002 NEC Corporation
- * Copyright (C) 2002 Miles Bader <miles@gnu.org>
+ * Copyright (C) 2002,03 NEC Electronics Corporation
+ * Copyright (C) 2002,03 Miles Bader <miles@gnu.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file COPYING in the main directory of this
@@ -14,6 +14,117 @@
#ifndef __V850_FLAT_H__
#define __V850_FLAT_H__
-#define flat_argvp_envp_on_stack() 0
+/* The amount by which a relocation can exceed the program image limits
+ without being regarded as an error. On the v850, the relocations of
+ some base-pointers can be offset by 0x8000 (to allow better usage of the
+ space offered by 16-bit signed offsets -- in most cases the offsets used
+ with such a base-pointer will be negative). */
+
+#define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000))
+
+#define flat_stack_align(sp) /* nothing needed */
+#define flat_argvp_envp_on_stack() 0
+#define flat_old_ram_flag(flags) (flags)
+
+/* We store the type of relocation in the top 4 bits of the `relval.' */
+
+/* Convert a relocation entry into an address. */
+static inline unsigned long
+flat_get_relocate_addr (unsigned long relval)
+{
+ return relval & 0x0fffffff; /* Mask out top 4-bits */
+}
+
+#define flat_v850_get_reloc_type(relval) ((relval) >> 28)
+
+#define FLAT_V850_R_32 0 /* Normal 32-bit reloc */
+#define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */
+#define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */
+
+/* Extract the address to be relocated from the symbol reference at RP;
+ RELVAL is the raw relocation-table entry from which RP is derived.
+ For the v850, RP should always be half-word aligned. */
+static inline unsigned long flat_get_addr_from_rp (unsigned long *rp,
+ unsigned long relval)
+{
+ short *srp = (short *)rp;
+
+ switch (flat_v850_get_reloc_type (relval))
+ {
+ case FLAT_V850_R_32:
+ /* Simple 32-bit address. */
+ return srp[0] | (srp[1] << 16);
+
+ case FLAT_V850_R_HI16S_LO16:
+ /* The high and low halves of the address are in the 16
+ bits at RP, and the 2nd word of the 32-bit instruction
+ following that, respectively. The low half is _signed_
+ so we have to sign-extend it and add it to the upper
+ half instead of simply or-ing them together.
+
+ Unlike most relocated address, this one is stored in
+ native (little-endian) byte-order to avoid problems with
+ trashing the low-order bit, so we have to convert to
+ network-byte-order before returning, as that's what the
+ caller expects. */
+ return htonl ((srp[0] << 16) + srp[2]);
+
+ case FLAT_V850_R_HI16S_LO15:
+ /* The high and low halves of the address are in the 16
+ bits at RP, and the upper 15 bits of the 2nd word of the
+ 32-bit instruction following that, respectively. The
+ low half is _signed_ so we have to sign-extend it and
+ add it to the upper half instead of simply or-ing them
+ together. The lowest bit is always zero.
+
+ Unlike most relocated address, this one is stored in
+ native (little-endian) byte-order to avoid problems with
+ trashing the low-order bit, so we have to convert to
+ network-byte-order before returning, as that's what the
+ caller expects. */
+ return htonl ((srp[0] << 16) + (srp[2] & ~0x1));
+
+ default:
+ return ~0; /* bogus value */
+ }
+}
+
+/* Insert the address ADDR into the symbol reference at RP;
+ RELVAL is the raw relocation-table entry from which RP is derived.
+ For the v850, RP should always be half-word aligned. */
+static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr,
+ unsigned long relval)
+{
+ short *srp = (short *)rp;
+
+ switch (flat_v850_get_reloc_type (relval)) {
+ case FLAT_V850_R_32:
+ /* Simple 32-bit address. */
+ srp[0] = addr & 0xFFFF;
+ srp[1] = (addr >> 16);
+ break;
+
+ case FLAT_V850_R_HI16S_LO16:
+ /* The high and low halves of the address are in the 16
+ bits at RP, and the 2nd word of the 32-bit instruction
+ following that, respectively. The low half is _signed_
+ so we must carry its sign bit to the upper half before
+ writing the upper half. */
+ srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
+ srp[2] = addr & 0xFFFF;
+ break;
+
+ case FLAT_V850_R_HI16S_LO15:
+ /* The high and low halves of the address are in the 16
+ bits at RP, and the upper 15 bits of the 2nd word of the
+ 32-bit instruction following that, respectively. The
+ low half is _signed_ so we must carry its sign bit to
+ the upper half before writing the upper half. The
+ lowest bit we preserve from the existing instruction. */
+ srp[0] = (addr >> 16) + ((addr >> 15) & 0x1);
+ srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1);
+ break;
+ }
+}
#endif /* __V850_FLAT_H__ */
diff --git a/include/asm-v850/mmu_context.h b/include/asm-v850/mmu_context.h
index 24301a46a92e..f521c8050d3c 100644
--- a/include/asm-v850/mmu_context.h
+++ b/include/asm-v850/mmu_context.h
@@ -3,9 +3,9 @@
#define destroy_context(mm) ((void)0)
#define init_new_context(tsk,mm) 0
-#define switch_mm(prev,next,tsk,cpu) ((void)0)
+#define switch_mm(prev,next,tsk) ((void)0)
#define deactivate_mm(tsk,mm) do { } while (0)
#define activate_mm(prev,next) ((void)0)
-#define enter_lazy_tlb(mm,tsk,cpu) ((void)0)
+#define enter_lazy_tlb(mm,tsk) ((void)0)
#endif /* __V850_MMU_CONTEXT_H__ */
diff --git a/include/asm-x86_64/div64.h b/include/asm-x86_64/div64.h
index 2c94d0762fe0..6cd978cefb28 100644
--- a/include/asm-x86_64/div64.h
+++ b/include/asm-x86_64/div64.h
@@ -1,14 +1 @@
-#ifndef __X86_64_DIV64
-#define __X86_64_DIV64
-
-/*
- * Hey, we're already 64-bit, no
- * need to play games..
- */
-#define do_div(n,base) ({ \
- int __res; \
- __res = ((unsigned long) (n)) % (unsigned) (base); \
- (n) = ((unsigned long) (n)) / (unsigned) (base); \
- __res; })
-
-#endif
+#include <asm-generic/div64.h>
diff --git a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h
index 41fc9820ee94..8f80f157035e 100644
--- a/include/asm-x86_64/mmu_context.h
+++ b/include/asm-x86_64/mmu_context.h
@@ -17,20 +17,21 @@ void destroy_context(struct mm_struct *mm);
#ifdef CONFIG_SMP
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
if (read_pda(mmu_state) == TLBSTATE_OK)
write_pda(mmu_state, TLBSTATE_LAZY);
}
#else
-static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
{
}
#endif
static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
- struct task_struct *tsk, unsigned cpu)
+ struct task_struct *tsk)
{
+ unsigned cpu = smp_processor_id();
if (likely(prev != next)) {
/* stop flush ipis for the previous mm */
clear_bit(cpu, &prev->cpu_vm_mask);
@@ -68,7 +69,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
} while(0)
#define activate_mm(prev, next) \
- switch_mm((prev),(next),NULL,smp_processor_id())
+ switch_mm((prev),(next),NULL)
#endif
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index c1a69000c8d7..398c530270c2 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -40,8 +40,7 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
- NODE_DATA(nid)->node_size)
-#define node_size(nid) (NODE_DATA(nid)->node_size)
+ NODE_DATA(nid)->node_spanned_pages)
#define local_mapnr(kvaddr) \
( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
diff --git a/include/linux/acct.h b/include/linux/acct.h
index 0b4ae8298a0e..69389c4af8e4 100644
--- a/include/linux/acct.h
+++ b/include/linux/acct.h
@@ -78,7 +78,7 @@ struct acct
#ifdef CONFIG_BSD_PROCESS_ACCT
struct super_block;
extern void acct_auto_close(struct super_block *sb);
-extern int acct_process(long exitcode);
+extern void acct_process(long exitcode);
#else
#define acct_auto_close(x) do { } while (0)
#define acct_process(x) do { } while (0)
diff --git a/include/linux/affs_fs.h b/include/linux/affs_fs.h
index 47ed05c8b744..c849309b1131 100644
--- a/include/linux/affs_fs.h
+++ b/include/linux/affs_fs.h
@@ -41,9 +41,9 @@ extern int affs_init_bitmap(struct super_block *sb);
/* namei.c */
extern int affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
-extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
extern int affs_unlink(struct inode *dir, struct dentry *dentry);
-extern int affs_create(struct inode *dir, struct dentry *dentry, int mode);
+extern int affs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
extern int affs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
extern int affs_rmdir(struct inode *dir, struct dentry *dentry);
extern int affs_link(struct dentry *olddentry, struct inode *dir,
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 786ea3563752..2e7f92aa1dc2 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -22,11 +22,62 @@ typedef struct elevator_s elevator_t;
struct request_pm_state;
#define BLKDEV_MIN_RQ 4
-#define BLKDEV_MAX_RQ 128
+#define BLKDEV_MAX_RQ 128 /* Default maximum */
+
+/*
+ * This is the per-process anticipatory I/O scheduler state.
+ */
+struct as_io_context {
+ spinlock_t lock;
+
+ void (*dtor)(struct as_io_context *aic); /* destructor */
+ void (*exit)(struct as_io_context *aic); /* called on task exit */
+
+ unsigned long state;
+ atomic_t nr_queued; /* queued reads & sync writes */
+ atomic_t nr_dispatched; /* number of requests gone to the drivers */
+
+ /* IO History tracking */
+ /* Thinktime */
+ unsigned long last_end_request;
+ unsigned long ttime_total;
+ unsigned long ttime_samples;
+ unsigned long ttime_mean;
+ /* Layout pattern */
+ long seek_samples;
+ sector_t last_request_pos;
+ sector_t seek_total;
+ sector_t seek_mean;
+};
+
+/*
+ * This is the per-process I/O subsystem state. It is refcounted and
+ * kmalloc'ed. Currently all fields are modified in process io context
+ * (apart from the atomic refcount), so require no locking.
+ */
+struct io_context {
+ atomic_t refcount;
+ pid_t pid;
+
+ /*
+ * For request batching
+ */
+ unsigned long last_waited; /* Time last woken after wait for request */
+ int nr_batch_requests; /* Number of requests left in the batch */
+
+ struct as_io_context *aic;
+};
+
+void put_io_context(struct io_context *ioc);
+void exit_io_context(void);
+struct io_context *get_io_context(int gfp_flags);
+void copy_io_context(struct io_context **pdst, struct io_context **psrc);
+void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
struct request_list {
int count[2];
mempool_t *rq_pool;
+ wait_queue_head_t wait[2];
};
/*
@@ -268,8 +319,15 @@ struct request_queue
spinlock_t *queue_lock;
/*
+ * queue kobject
+ */
+ struct kobject kobj;
+
+ /*
* queue settings
*/
+ unsigned long nr_requests; /* Max # of requests */
+
unsigned short max_sectors;
unsigned short max_phys_segments;
unsigned short max_hw_segments;
@@ -299,6 +357,8 @@ struct request_queue
#define QUEUE_FLAG_CLUSTER 0 /* cluster several segments into 1 */
#define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */
#define QUEUE_FLAG_STOPPED 2 /* queue is stopped */
+#define QUEUE_FLAG_READFULL 3 /* write queue has been filled */
+#define QUEUE_FLAG_WRITEFULL 4 /* read queue has been filled */
#define blk_queue_plugged(q) !list_empty(&(q)->plug_list)
#define blk_queue_tagged(q) test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
@@ -314,6 +374,30 @@ struct request_queue
#define rq_data_dir(rq) ((rq)->flags & 1)
+static inline int blk_queue_full(struct request_queue *q, int rw)
+{
+ if (rw == READ)
+ return test_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+ return test_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+static inline void blk_set_queue_full(struct request_queue *q, int rw)
+{
+ if (rw == READ)
+ set_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+ else
+ set_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+static inline void blk_clear_queue_full(struct request_queue *q, int rw)
+{
+ if (rw == READ)
+ clear_bit(QUEUE_FLAG_READFULL, &q->queue_flags);
+ else
+ clear_bit(QUEUE_FLAG_WRITEFULL, &q->queue_flags);
+}
+
+
/*
* mergeable request must not have _NOMERGE or _BARRIER bit set, nor may
* it already be started by driver.
@@ -397,6 +481,8 @@ struct sec_size {
unsigned block_size_bits;
};
+extern int blk_register_queue(struct gendisk *disk);
+extern void blk_unregister_queue(struct gendisk *disk);
extern void register_disk(struct gendisk *dev);
extern void generic_make_request(struct bio *bio);
extern void blk_put_request(struct request *);
@@ -560,6 +646,10 @@ static inline void put_dev_sector(Sector p)
page_cache_release(p.v);
}
+struct work_struct;
+int kblockd_schedule_work(struct work_struct *work);
+void kblockd_flush(void);
+
#ifdef CONFIG_LBD
# include <asm/div64.h>
# define sector_div(a, b) do_div(a, b)
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 22d3ac8efc6b..1f468b0491ed 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -167,6 +167,7 @@ struct buffer_head *__find_get_block(struct block_device *, sector_t, int);
struct buffer_head * __getblk(struct block_device *, sector_t, int);
void __brelse(struct buffer_head *);
void __bforget(struct buffer_head *);
+void __breadahead(struct block_device *, sector_t block, int size);
struct buffer_head *__bread(struct block_device *, sector_t block, int size);
struct buffer_head *alloc_buffer_head(int gfp_flags);
void free_buffer_head(struct buffer_head * bh);
@@ -241,6 +242,12 @@ sb_bread(struct super_block *sb, sector_t block)
return __bread(sb->s_bdev, block, sb->s_blocksize);
}
+static inline void
+sb_breadahead(struct super_block *sb, sector_t block)
+{
+ __breadahead(sb->s_bdev, block, sb->s_blocksize);
+}
+
static inline struct buffer_head *
sb_getblk(struct super_block *sb, sector_t block)
{
diff --git a/include/linux/coda_linux.h b/include/linux/coda_linux.h
index b22d34fcfb6d..650a6f997f8a 100644
--- a/include/linux/coda_linux.h
+++ b/include/linux/coda_linux.h
@@ -38,7 +38,7 @@ extern struct file_operations coda_ioctl_operations;
int coda_open(struct inode *i, struct file *f);
int coda_flush(struct file *f);
int coda_release(struct inode *i, struct file *f);
-int coda_permission(struct inode *inode, int mask);
+int coda_permission(struct inode *inode, int mask, struct nameidata *nd);
int coda_revalidate_inode(struct dentry *);
int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
int coda_setattr(struct dentry *, struct iattr *);
diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
index 076b1b268c7d..3fb888cc0c34 100644
--- a/include/linux/compat_ioctl.h
+++ b/include/linux/compat_ioctl.h
@@ -117,7 +117,7 @@ COMPATIBLE_IOCTL(START_ARRAY)
COMPATIBLE_IOCTL(STOP_ARRAY)
COMPATIBLE_IOCTL(STOP_ARRAY_RO)
COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
-#ifdef CONFIG_DM
+#ifdef CONFIG_BLK_DEV_DM
/* DM */
COMPATIBLE_IOCTL(DM_VERSION)
COMPATIBLE_IOCTL(DM_REMOVE_ALL)
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 1442779bd893..a25d9f0443a4 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -10,6 +10,7 @@
#include <linux/rcupdate.h>
#include <asm/bug.h>
+struct nameidata;
struct vfsmount;
/*
@@ -106,7 +107,7 @@ struct dentry {
#define DNAME_INLINE_LEN (sizeof(struct dentry)-offsetof(struct dentry,d_iname))
struct dentry_operations {
- int (*d_revalidate)(struct dentry *, int);
+ int (*d_revalidate)(struct dentry *, struct nameidata *);
int (*d_hash) (struct dentry *, struct qstr *);
int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
int (*d_delete)(struct dentry *);
diff --git a/include/linux/device.h b/include/linux/device.h
index 1bd92551c077..2795b85ac6f1 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <asm/semaphore.h>
#include <asm/atomic.h>
@@ -95,7 +96,7 @@ struct bus_attribute {
#define BUS_ATTR(_name,_mode,_show,_store) \
struct bus_attribute bus_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
};
@@ -136,7 +137,7 @@ struct driver_attribute {
#define DRIVER_ATTR(_name,_mode,_show,_store) \
struct driver_attribute driver_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
};
@@ -176,7 +177,7 @@ struct class_attribute {
#define CLASS_ATTR(_name,_mode,_show,_store) \
struct class_attribute class_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
};
@@ -215,6 +216,8 @@ extern void class_device_initialize(struct class_device *);
extern int class_device_add(struct class_device *);
extern void class_device_del(struct class_device *);
+extern int class_device_rename(struct class_device *, char *);
+
extern struct class_device * class_device_get(struct class_device *);
extern void class_device_put(struct class_device *);
@@ -226,7 +229,7 @@ struct class_device_attribute {
#define CLASS_DEVICE_ATTR(_name,_mode,_show,_store) \
struct class_device_attribute class_device_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
};
@@ -324,7 +327,7 @@ struct device_attribute {
#define DEVICE_ATTR(_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_name = { \
- .attr = {.name = __stringify(_name), .mode = _mode }, \
+ .attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
};
diff --git a/include/linux/efs_fs.h b/include/linux/efs_fs.h
index c78e9c2a7b3a..1640eb875d4e 100644
--- a/include/linux/efs_fs.h
+++ b/include/linux/efs_fs.h
@@ -46,7 +46,7 @@ extern int efs_statfs(struct super_block *, struct kstatfs *);
extern void efs_read_inode(struct inode *);
extern efs_block_t efs_map_block(struct inode *, efs_block_t);
-extern struct dentry *efs_lookup(struct inode *, struct dentry *);
+extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
extern int efs_bmap(struct inode *, int);
#endif /* __EFS_FS_H__ */
diff --git a/include/linux/eisa.h b/include/linux/eisa.h
index d77fdf0f9f01..93e4c5503d46 100644
--- a/include/linux/eisa.h
+++ b/include/linux/eisa.h
@@ -4,6 +4,8 @@
#define EISA_SIG_LEN 8
#define EISA_MAX_SLOTS 8
+#define EISA_MAX_RESOURCES 4
+
/* A few EISA constants/offsets... */
#define EISA_DMA1_STATUS 8
@@ -17,6 +19,10 @@
#define EISA_INT1_EDGE_LEVEL 0x4D0
#define EISA_INT2_EDGE_LEVEL 0x4D1
#define EISA_VENDOR_ID_OFFSET 0xC80
+#define EISA_CONFIG_OFFSET 0xC84
+
+#define EISA_CONFIG_ENABLED 1
+#define EISA_CONFIG_FORCED 2
/* The EISA signature, in ASCII form, null terminated */
struct eisa_device_id {
@@ -26,19 +32,28 @@ struct eisa_device_id {
/* There is not much we can say about an EISA device, apart from
* signature, slot number, and base address. dma_mask is set by
- * default to 32 bits.*/
+ * default to parent device mask..*/
struct eisa_device {
struct eisa_device_id id;
int slot;
+ int state;
unsigned long base_addr;
- struct resource res;
+ struct resource res[EISA_MAX_RESOURCES];
u64 dma_mask;
struct device dev; /* generic device */
};
#define to_eisa_device(n) container_of(n, struct eisa_device, dev)
+static inline int eisa_get_region_index (void *addr)
+{
+ unsigned long x = (unsigned long) addr;
+
+ x &= 0xc00;
+ return (x >> 12);
+}
+
struct eisa_driver {
const struct eisa_device_id *id_table;
struct device_driver driver;
@@ -69,6 +84,8 @@ struct eisa_root_device {
struct resource *res;
unsigned long bus_base_addr;
int slots; /* Max slot number */
+ int force_probe; /* Probe even when no slot 0 */
+ u64 dma_mask; /* from bridge device */
int bus_nr; /* Set by eisa_root_register */
struct resource eisa_root_res; /* ditto */
};
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index 522e51609ef3..b0e70562be94 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -15,6 +15,9 @@ typedef int (elevator_queue_empty_fn) (request_queue_t *);
typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *);
+typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
+typedef int (elevator_may_queue_fn) (request_queue_t *, int);
+
typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int);
typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
@@ -32,6 +35,7 @@ struct elevator_s
elevator_remove_req_fn *elevator_remove_req_fn;
elevator_queue_empty_fn *elevator_queue_empty_fn;
+ elevator_completed_req_fn *elevator_completed_req_fn;
elevator_request_list_fn *elevator_former_req_fn;
elevator_request_list_fn *elevator_latter_req_fn;
@@ -39,6 +43,8 @@ struct elevator_s
elevator_set_req_fn *elevator_set_req_fn;
elevator_put_req_fn *elevator_put_req_fn;
+ elevator_may_queue_fn *elevator_may_queue_fn;
+
elevator_init_fn *elevator_init_fn;
elevator_exit_fn *elevator_exit_fn;
@@ -62,8 +68,10 @@ extern int elv_queue_empty(request_queue_t *);
extern struct request *elv_next_request(struct request_queue *q);
extern struct request *elv_former_request(request_queue_t *, struct request *);
extern struct request *elv_latter_request(request_queue_t *, struct request *);
-extern int elv_register_queue(struct gendisk *);
-extern void elv_unregister_queue(struct gendisk *);
+extern int elv_register_queue(request_queue_t *q);
+extern void elv_unregister_queue(request_queue_t *q);
+extern int elv_may_queue(request_queue_t *, int);
+extern void elv_completed_request(request_queue_t *, struct request *);
extern int elv_set_request(request_queue_t *, struct request *, int);
extern void elv_put_request(request_queue_t *, struct request *);
@@ -81,6 +89,11 @@ extern elevator_t elevator_noop;
*/
extern elevator_t iosched_deadline;
+/*
+ * anticipatory I/O scheduler
+ */
+extern elevator_t iosched_as;
+
extern int elevator_init(request_queue_t *, elevator_t *);
extern void elevator_exit(request_queue_t *);
extern inline int elv_rq_merge_ok(struct request *, struct bio *);
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index 60f8cadb1f50..f89acbe8183a 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -14,6 +14,8 @@
#ifndef _LINUX_EVENTPOLL_H
#define _LINUX_EVENTPOLL_H
+#include <linux/types.h>
+
/* Valid opcodes to issue to sys_epoll_ctl() */
#define EPOLL_CTL_ADD 1
@@ -55,8 +57,37 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event *events, int maxeven
/* Used to initialize the epoll bits inside the "struct file" */
void eventpoll_init_file(struct file *file);
-/* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
-void eventpoll_release(struct file *file);
+/* Used to release the epoll bits inside the "struct file" */
+void eventpoll_release_file(struct file *file);
+
+/*
+ * This is called from inside fs/file_table.c:__fput() to unlink files
+ * from the eventpoll interface. We need to have this facility to cleanup
+ * correctly files that are closed without being removed from the eventpoll
+ * interface.
+ */
+static inline void eventpoll_release(struct file *file)
+{
+
+ /*
+ * Fast check to avoid the get/release of the semaphore. Since
+ * we're doing this outside the semaphore lock, it might return
+ * false negatives, but we don't care. It'll help in 99.99% of cases
+ * to avoid the semaphore lock. False positives simply cannot happen
+ * because the file in on the way to be removed and nobody ( but
+ * eventpoll ) has still a reference to this file.
+ */
+ if (likely(list_empty(&file->f_ep_links)))
+ return;
+
+ /*
+ * The file is being closed while it is still linked to an epoll
+ * descriptor. We need to handle this by correctly unlinking it
+ * from its containers.
+ */
+ eventpoll_release_file(file);
+}
+
#else
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index f077563bcfc3..c360f84fed3d 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -636,10 +636,14 @@ struct dx_hash_info
struct ext3_iloc
{
struct buffer_head *bh;
- struct ext3_inode *raw_inode;
+ unsigned long offset;
unsigned long block_group;
};
+static inline struct ext3_inode *ext3_raw_inode(struct ext3_iloc *iloc)
+{
+ return (struct ext3_inode *) (iloc->bh->b_data + iloc->offset);
+}
/*
* This structure is stuffed into the struct file's private_data field
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index 1a6a6c5922f7..1181cfae7142 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -62,6 +62,16 @@ struct ext3_inode_info {
__u32 i_prealloc_count;
#endif
__u32 i_dir_start_lookup;
+#ifdef CONFIG_EXT3_FS_XATTR
+ /*
+ * Extended attributes can be read independently of the main file
+ * data. Taking i_sem even when reading would cause contention
+ * between readers of EAs and writers of regular file data, so
+ * instead we synchronize on xattr_sem when reading or changing
+ * EAs.
+ */
+ struct rw_semaphore xattr_sem;
+#endif
#ifdef CONFIG_EXT3_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
diff --git a/include/linux/flat.h b/include/linux/flat.h
index 7643a3f9d3f5..ec56852e2659 100644
--- a/include/linux/flat.h
+++ b/include/linux/flat.h
@@ -1,7 +1,7 @@
-
-/* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
- * The Silver Hammer Group, Ltd.
- * Copyright (C) 2002 David McCullough <davidm@snapgear.com>
+/*
+ * Copyright (C) 2002-2003 David McCullough <davidm@snapgear.com>
+ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
+ * The Silver Hammer Group, Ltd.
*
* This file provides the definitions and structures needed to
* support uClinux flat-format executables.
@@ -10,10 +10,18 @@
#ifndef _LINUX_FLAT_H
#define _LINUX_FLAT_H
+#ifdef __KERNEL__
#include <asm/flat.h>
+#endif
#define FLAT_VERSION 0x00000004L
+#ifdef CONFIG_BINFMT_SHARED_FLAT
+#define MAX_SHARED_LIBS (4)
+#else
+#define MAX_SHARED_LIBS (1)
+#endif
+
/*
* To make everything easier to port and manage cross platform
* development, all fields are in network byte order.
@@ -46,8 +54,10 @@ struct flat_hdr {
#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
#define FLAT_FLAG_GZIP 0x0004 /* all but the header is compressed */
#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
+#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
+#ifdef __KERNEL__ /* so systems without linux headers can compile the apps */
/*
* While it would be nice to keep this header clean, users of older
* tools still need this support in the kernel. So this section is
@@ -85,4 +95,6 @@ typedef union {
} reloc;
} flat_v2_reloc_t;
+#endif /* __KERNEL__ */
+
#endif /* _LINUX_FLAT_H */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c3bda88631bc..77dd4b13dc43 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -420,6 +420,8 @@ struct file_ra_state {
unsigned long ahead_start; /* Ahead window */
unsigned long ahead_size;
unsigned long ra_pages; /* Maximum readahead window */
+ unsigned long mmap_hit; /* Cache hit stat for mmap accesses */
+ unsigned long mmap_miss; /* Cache miss stat for mmap accesses */
};
struct file {
@@ -639,7 +641,7 @@ static inline void unlock_super(struct super_block * sb)
/*
* VFS helper functions..
*/
-extern int vfs_create(struct inode *, struct dentry *, int);
+extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
extern int vfs_mkdir(struct inode *, struct dentry *, int);
extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
extern int vfs_symlink(struct inode *, struct dentry *, const char *);
@@ -730,8 +732,8 @@ struct file_operations {
};
struct inode_operations {
- int (*create) (struct inode *,struct dentry *,int);
- struct dentry * (*lookup) (struct inode *,struct dentry *);
+ int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
+ struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
int (*link) (struct dentry *,struct inode *,struct dentry *);
int (*unlink) (struct inode *,struct dentry *);
int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -743,7 +745,7 @@ struct inode_operations {
int (*readlink) (struct dentry *, char __user *,int);
int (*follow_link) (struct dentry *, struct nameidata *);
void (*truncate) (struct inode *);
- int (*permission) (struct inode *, int);
+ int (*permission) (struct inode *, int, struct nameidata *);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
@@ -1121,7 +1123,7 @@ extern int do_remount_sb(struct super_block *sb, int flags,
extern sector_t bmap(struct inode *, sector_t);
extern int setattr_mask(unsigned int);
extern int notify_change(struct dentry *, struct iattr *);
-extern int permission(struct inode *, int);
+extern int permission(struct inode *, int, struct nameidata *);
extern int vfs_permission(struct inode *, int);
extern int get_write_access(struct inode *);
extern int deny_write_access(struct file *);
@@ -1291,7 +1293,7 @@ extern int simple_prepare_write(struct file *file, struct page *page,
extern int simple_commit_write(struct file *file, struct page *page,
unsigned offset, unsigned to);
-extern struct dentry *simple_lookup(struct inode *, struct dentry *);
+extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
extern struct file_operations simple_dir_operations;
extern struct inode_operations simple_dir_inode_operations;
diff --git a/include/linux/hfs_fs.h b/include/linux/hfs_fs.h
index 40971822e3e4..7bebd13150dd 100644
--- a/include/linux/hfs_fs.h
+++ b/include/linux/hfs_fs.h
@@ -234,7 +234,7 @@ extern struct hfs_cat_entry *hfs_cat_get(struct hfs_mdb *,
const struct hfs_cat_key *);
/* dir.c */
-extern int hfs_create(struct inode *, struct dentry *, int);
+extern int hfs_create(struct inode *, struct dentry *, int, struct nameidata *);
extern int hfs_mkdir(struct inode *, struct dentry *, int);
extern int hfs_unlink(struct inode *, struct dentry *);
extern int hfs_rmdir(struct inode *, struct dentry *);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index da2eaeb18118..21e48723b386 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -94,8 +94,8 @@ struct softirq_action
asmlinkage void do_softirq(void);
extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data);
extern void softirq_init(void);
-#define __cpu_raise_softirq(cpu, nr) do { softirq_pending(cpu) |= 1UL << (nr); } while (0)
-extern void FASTCALL(cpu_raise_softirq(unsigned int cpu, unsigned int nr));
+#define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0)
+extern void FASTCALL(raise_softirq_irqoff(unsigned int nr));
extern void FASTCALL(raise_softirq(unsigned int nr));
#ifndef invoke_softirq
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 9193a8df0122..26d6293ed4c9 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -43,6 +43,7 @@ struct resource_list {
#define IORESOURCE_SHADOWABLE 0x00010000
#define IORESOURCE_BUS_HAS_VGA 0x00080000
+#define IORESOURCE_DISABLED 0x10000000
#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
#define IORESOURCE_BUSY 0x80000000 /* Driver has marked this resource busy */
diff --git a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h
index 3f49c2ba63ed..03b3e17de805 100644
--- a/include/linux/irq_cpustat.h
+++ b/include/linux/irq_cpustat.h
@@ -29,10 +29,6 @@ extern irq_cpustat_t irq_stat[]; /* defined in asm/hardirq.h */
/* arch independent irq_stat fields */
#define softirq_pending(cpu) __IRQ_STAT((cpu), __softirq_pending)
#define local_softirq_pending() softirq_pending(smp_processor_id())
-#define syscall_count(cpu) __IRQ_STAT((cpu), __syscall_count)
-#define local_syscall_count() syscall_count(smp_processor_id())
-#define ksoftirqd_task(cpu) __IRQ_STAT((cpu), __ksoftirqd_task)
-#define local_ksoftirqd_task() ksoftirqd_task(smp_processor_id())
/* arch dependent irq_stat fields */
#define nmi_count(cpu) __IRQ_STAT((cpu), __nmi_count) /* i386 */
diff --git a/include/linux/iso_fs.h b/include/linux/iso_fs.h
index 4763b595287a..223f161da018 100644
--- a/include/linux/iso_fs.h
+++ b/include/linux/iso_fs.h
@@ -227,7 +227,7 @@ extern int isofs_name_translate(struct iso_directory_record *, char *, struct in
int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
extern struct buffer_head *isofs_bread(struct inode *, sector_t);
extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h
index 88425e94cdc5..9971827a3c4b 100644
--- a/include/linux/kernel_stat.h
+++ b/include/linux/kernel_stat.h
@@ -31,7 +31,8 @@ struct kernel_stat {
DECLARE_PER_CPU(struct kernel_stat, kstat);
#define kstat_cpu(cpu) per_cpu(kstat, cpu)
-#define kstat_this_cpu kstat_cpu(smp_processor_id())
+/* Must have preemption disabled for this to be meaningful. */
+#define kstat_this_cpu __get_cpu_var(kstat)
extern unsigned long nr_context_switches(void);
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 5d42248dd95f..e744a55d07d5 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -39,6 +39,8 @@ extern void kobject_cleanup(struct kobject *);
extern int kobject_add(struct kobject *);
extern void kobject_del(struct kobject *);
+extern void kobject_rename(struct kobject *, char *new_name);
+
extern int kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 492bc8aeb053..858914b2dbd3 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -339,9 +339,14 @@ static inline void set_page_zone(struct page *page, unsigned long zone_num)
page->flags |= zone_num << ZONE_SHIFT;
}
-static inline void * lowmem_page_address(struct page *page)
+#ifndef CONFIG_DISCONTIGMEM
+/* The array of struct pages - for discontigmem use pgdat->lmem_map */
+extern struct page *mem_map;
+#endif
+
+static inline void *lowmem_page_address(struct page *page)
{
- return __va( ( (page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn) << PAGE_SHIFT);
+ return __va(page_to_pfn(page) << PAGE_SHIFT);
}
#if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL)
@@ -395,11 +400,6 @@ static inline int page_mapped(struct page *page)
#define VM_FAULT_MINOR 1
#define VM_FAULT_MAJOR 2
-#ifndef CONFIG_DISCONTIGMEM
-/* The array of struct pages - for discontigmem use pgdat->lmem_map */
-extern struct page *mem_map;
-#endif
-
extern void show_free_areas(void);
struct page *shmem_nopage(struct vm_area_struct * vma,
@@ -571,10 +571,6 @@ void page_cache_readahead(struct address_space *mapping,
struct file_ra_state *ra,
struct file *filp,
unsigned long offset);
-void page_cache_readaround(struct address_space *mapping,
- struct file_ra_state *ra,
- struct file *filp,
- unsigned long offset);
void handle_ra_miss(struct address_space *mapping,
struct file_ra_state *ra, pgoff_t offset);
unsigned long max_sane_readahead(unsigned long nr);
@@ -609,5 +605,13 @@ extern struct page * follow_page(struct mm_struct *mm, unsigned long address,
int write);
extern int remap_page_range(struct vm_area_struct *vma, unsigned long from,
unsigned long to, unsigned long size, pgprot_t prot);
+
+#ifndef CONFIG_DEBUG_PAGEALLOC
+static inline void
+kernel_map_pages(struct page *page, int numpages, int enable)
+{
+}
+#endif
+
#endif /* __KERNEL__ */
#endif /* _LINUX_MM_H */
diff --git a/include/linux/mman.h b/include/linux/mman.h
index 474d1c046436..a8956f6588ad 100644
--- a/include/linux/mman.h
+++ b/include/linux/mman.h
@@ -9,7 +9,8 @@
#define MREMAP_MAYMOVE 1
#define MREMAP_FIXED 2
-extern int vm_enough_memory(long pages);
+extern int sysctl_overcommit_memory;
+extern int sysctl_overcommit_ratio;
extern atomic_t vm_committed_space;
#ifdef CONFIG_SMP
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 21e95664fdf8..e768f7ab8963 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -184,12 +184,17 @@ typedef struct pglist_data {
unsigned long *valid_addr_bitmap;
struct bootmem_data *bdata;
unsigned long node_start_pfn;
- unsigned long node_size;
+ unsigned long node_present_pages; /* total number of physical pages */
+ unsigned long node_spanned_pages; /* total size of physical page
+ range, including holes */
int node_id;
struct pglist_data *pgdat_next;
wait_queue_head_t kswapd_wait;
} pg_data_t;
+#define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages)
+#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages)
+
extern int numnodes;
extern struct pglist_data *pgdat_list;
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
index 4268ed112436..1ce9ba2f57b0 100644
--- a/include/linux/msdos_fs.h
+++ b/include/linux/msdos_fs.h
@@ -307,8 +307,8 @@ extern int fat_scan(struct inode *dir, const char *name,
struct msdos_dir_entry **res_de, loff_t *i_pos);
/* msdos/namei.c - these are for Umsdos */
-extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *);
-extern int msdos_create(struct inode *dir, struct dentry *dentry, int mode);
+extern struct dentry *msdos_lookup(struct inode *dir, struct dentry *, struct nameidata *);
+extern int msdos_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
extern int msdos_rmdir(struct inode *dir, struct dentry *dentry);
extern int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode);
extern int msdos_unlink(struct inode *dir, struct dentry *dentry);
@@ -317,8 +317,8 @@ extern int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
extern int msdos_fill_super(struct super_block *sb, void *data, int silent);
/* vfat/namei.c - these are for dmsdos */
-extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *);
-extern int vfat_create(struct inode *dir, struct dentry *dentry, int mode);
+extern struct dentry *vfat_lookup(struct inode *dir, struct dentry *, struct nameidata *);
+extern int vfat_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *);
extern int vfat_rmdir(struct inode *dir, struct dentry *dentry);
extern int vfat_unlink(struct inode *dir, struct dentry *dentry);
extern int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode);
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 16baf5cdb9c7..4117cd90a345 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -5,12 +5,22 @@
struct vfsmount;
+struct open_intent {
+ int flags;
+ int create_mode;
+};
+
struct nameidata {
struct dentry *dentry;
struct vfsmount *mnt;
struct qstr last;
unsigned int flags;
int last_type;
+
+ /* Intent data */
+ union {
+ struct open_intent open;
+ } intent;
};
/*
@@ -31,7 +41,12 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
#define LOOKUP_CONTINUE 4
#define LOOKUP_PARENT 16
#define LOOKUP_NOALT 32
-
+/*
+ * Intent data
+ */
+#define LOOKUP_OPEN (0x0100)
+#define LOOKUP_CREATE (0x0200)
+#define LOOKUP_ACCESS (0x0400)
extern int FASTCALL(__user_walk(const char __user *, unsigned, struct nameidata *));
#define user_path_walk(name,nd) \
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d79375c33273..3aef822b4493 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -561,7 +561,7 @@ static inline void __netif_schedule(struct net_device *dev)
cpu = smp_processor_id();
dev->next_sched = softnet_data[cpu].output_queue;
softnet_data[cpu].output_queue = dev;
- cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+ raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
}
}
@@ -612,7 +612,7 @@ static inline void dev_kfree_skb_irq(struct sk_buff *skb)
cpu = smp_processor_id();
skb->next = softnet_data[cpu].completion_queue;
softnet_data[cpu].completion_queue = skb;
- cpu_raise_softirq(cpu, NET_TX_SOFTIRQ);
+ raise_softirq_irqoff(NET_TX_SOFTIRQ);
local_irq_restore(flags);
}
}
@@ -779,7 +779,7 @@ static inline void __netif_rx_schedule(struct net_device *dev)
dev->quota += dev->weight;
else
dev->quota = dev->weight;
- __cpu_raise_softirq(cpu, NET_RX_SOFTIRQ);
+ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
local_irq_restore(flags);
}
@@ -805,7 +805,7 @@ static inline int netif_rx_reschedule(struct net_device *dev, int undo)
local_irq_save(flags);
cpu = smp_processor_id();
list_add_tail(&dev->poll_list, &softnet_data[cpu].poll_list);
- __cpu_raise_softirq(cpu, NET_RX_SOFTIRQ);
+ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
local_irq_restore(flags);
return 1;
}
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 3d7525998534..a6d594bb252c 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -240,7 +240,7 @@ extern struct inode *nfs_fhget(struct dentry *, struct nfs_fh *,
struct nfs_fattr *);
extern int __nfs_refresh_inode(struct inode *, struct nfs_fattr *);
extern int nfs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
-extern int nfs_permission(struct inode *, int);
+extern int nfs_permission(struct inode *, int, struct nameidata *);
extern int nfs_open(struct inode *, struct file *);
extern int nfs_release(struct inode *, struct file *);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 3ceb5d7da821..a219c58ad88e 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -543,7 +543,7 @@ void pcibios_update_irq(struct pci_dev *, int irq);
/* Generic PCI functions used internally */
-int pci_bus_exists(const struct list_head *list, int nr);
+extern struct pci_bus *pci_find_bus(int domain, int busnr);
struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata);
static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata)
{
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index c0144a1ba4cb..e2e54ee6186d 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -92,7 +92,7 @@ extern struct proc_dir_entry *proc_root_kcore;
extern void proc_root_init(void);
extern void proc_misc_init(void);
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry);
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
struct dentry *proc_pid_unhash(struct task_struct *p);
void proc_pid_flush(struct dentry *proc_dentry);
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
@@ -115,7 +115,7 @@ extern int proc_match(int, const char *,struct proc_dir_entry *);
* of the /proc/<pid> subdirectories.
*/
extern int proc_readdir(struct file *, void *, filldir_t);
-extern struct dentry *proc_lookup(struct inode *, struct dentry *);
+extern struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
extern struct file_operations proc_kcore_operations;
extern struct file_operations proc_kmsg_operations;
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 5710620989d5..53233c8fb3ef 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -110,21 +110,20 @@ struct qnx4_inode_info {
struct inode vfs_inode;
};
-extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
+extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
extern struct buffer_head *qnx4_getblk(struct inode *, int, int);
extern struct buffer_head *qnx4_bread(struct inode *, int, int);
-extern int qnx4_create(struct inode *dir, struct dentry *dentry, int mode);
extern struct inode_operations qnx4_file_inode_operations;
extern struct inode_operations qnx4_dir_inode_operations;
extern struct file_operations qnx4_file_operations;
extern struct file_operations qnx4_dir_operations;
extern int qnx4_is_free(struct super_block *sb, long block);
extern int qnx4_set_bitmap(struct super_block *sb, long block, int busy);
-extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode);
+extern int qnx4_create(struct inode *inode, struct dentry *dentry, int mode, struct nameidata *nd);
extern void qnx4_truncate(struct inode *inode);
extern void qnx4_free_inode(struct inode *inode);
extern int qnx4_unlink(struct inode *dir, struct dentry *dentry);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 77d017472dc7..fbf2d2b2a5be 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -306,6 +306,16 @@ int register_quota_format(struct quota_format_type *fmt);
void unregister_quota_format(struct quota_format_type *fmt);
void init_dquot_operations(struct dquot_operations *fsdqops);
+struct quota_module_name {
+ int qm_fmt_id;
+ char *qm_mod_name;
+};
+
+#define INIT_QUOTA_MODULE_NAMES {\
+ {QFMT_VFS_OLD, "quota_v1"},\
+ {QFMT_VFS_V0, "quota_v2"},\
+ {0, NULL}}
+
#else
# /* nodep */ include <sys/cdefs.h>
diff --git a/include/linux/sched.h b/include/linux/sched.h
index ca97376901b0..750f2a12cada 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -321,6 +321,8 @@ struct k_itimer {
};
+struct io_context; /* See blkdev.h */
+void exit_io_context(void);
struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
@@ -450,6 +452,8 @@ struct task_struct {
struct dentry *proc_dentry;
struct backing_dev_info *backing_dev_info;
+ struct io_context *io_context;
+
unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
};
@@ -481,6 +485,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PF_KSWAPD 0x00040000 /* I am kswapd */
#define PF_SWAPOFF 0x00080000 /* I am in swapoff */
#define PF_LESS_THROTTLE 0x01000000 /* Throttle me less: I clena memory */
+#define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */
#ifdef CONFIG_SMP
extern int set_cpus_allowed(task_t *p, unsigned long new_mask);
diff --git a/include/linux/security.h b/include/linux/security.h
index 9589f99c3ef3..4d91dfc52c52 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -49,6 +49,7 @@ extern int cap_bprm_secureexec(struct linux_binprm *bprm);
extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
extern void cap_task_reparent_to_init (struct task_struct *p);
extern int cap_syslog (int type);
+extern int cap_vm_enough_memory (long pages);
static inline int cap_netlink_send (struct sk_buff *skb)
{
@@ -958,6 +959,10 @@ struct swap_info_struct;
* See the syslog(2) manual page for an explanation of the @type values.
* @type contains the type of action.
* Return 0 if permission is granted.
+ * @vm_enough_memory:
+ * Check permissions for allocating a new virtual mapping.
+ * @pages contains the number of pages.
+ * Return 0 if permission is granted.
*
* @register_security:
* allow module stacking.
@@ -989,6 +994,7 @@ struct security_operations {
int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
int (*quota_on) (struct file * f);
int (*syslog) (int type);
+ int (*vm_enough_memory) (long pages);
int (*bprm_alloc_security) (struct linux_binprm * bprm);
void (*bprm_free_security) (struct linux_binprm * bprm);
@@ -1238,6 +1244,11 @@ static inline int security_syslog(int type)
return security_ops->syslog(type);
}
+static inline int security_vm_enough_memory(long pages)
+{
+ return security_ops->vm_enough_memory(pages);
+}
+
static inline int security_bprm_alloc (struct linux_binprm *bprm)
{
return security_ops->bprm_alloc_security (bprm);
@@ -1898,6 +1909,11 @@ static inline int security_syslog(int type)
return cap_syslog(type);
}
+static inline int security_vm_enough_memory(long pages)
+{
+ return cap_vm_enough_memory(pages);
+}
+
static inline int security_bprm_alloc (struct linux_binprm *bprm)
{
return 0;
diff --git a/include/linux/sem.h b/include/linux/sem.h
index 2821bc07f647..6e13e5efc163 100644
--- a/include/linux/sem.h
+++ b/include/linux/sem.h
@@ -109,7 +109,6 @@ struct sem_queue {
int id; /* internal sem id */
struct sembuf * sops; /* array of pending operations */
int nsops; /* number of operations */
- int alter; /* operation will alter semaphore */
};
/* Each task has a list of undo requests. They are executed automatically
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 843c8d638d29..d797c981f37e 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -114,6 +114,10 @@ extern kmem_cache_t *signal_cachep;
extern kmem_cache_t *sighand_cachep;
extern kmem_cache_t *bio_cachep;
+void ptrinfo(unsigned long addr);
+
+extern atomic_t slab_reclaim_pages;
+
#endif /* __KERNEL__ */
#endif /* _LINUX_SLAB_H */
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index f054416c8145..441c0d91f583 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -10,9 +10,11 @@
#define _SYSFS_H_
struct kobject;
+struct module;
struct attribute {
char * name;
+ struct module * owner;
mode_t mode;
};
@@ -37,6 +39,9 @@ sysfs_create_dir(struct kobject *);
extern void
sysfs_remove_dir(struct kobject *);
+extern void
+sysfs_rename_dir(struct kobject *, char *new_name);
+
extern int
sysfs_create_file(struct kobject *, struct attribute *);
diff --git a/include/linux/umsdos_fs.p b/include/linux/umsdos_fs.p
index 7034b7eb6b16..1c284c5a7aec 100644
--- a/include/linux/umsdos_fs.p
+++ b/include/linux/umsdos_fs.p
@@ -10,7 +10,7 @@ char * umsdos_d_path(struct dentry *, char *, int);
void umsdos_lookup_patch_new(struct dentry *, struct umsdos_info *);
int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry);
struct dentry *umsdos_lookup_x ( struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_lookup(struct inode *, struct dentry *);
+struct dentry *UMSDOS_lookup(struct inode *, struct dentry *, struct nameidata *);
struct dentry *umsdos_lookup_dentry(struct dentry *, char *, int, int);
struct dentry *umsdos_covered(struct dentry *, char *, int);
@@ -92,7 +92,7 @@ int UMSDOS_rename (struct inode *old_dir,
/* rdir.c 22/03/95 03.31.42 */
struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo);
-struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry);
+struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd);
static inline struct umsdos_inode_info *UMSDOS_I(struct inode *inode)
{
diff --git a/init/Kconfig b/init/Kconfig
index d3a9874335aa..ab6212b48202 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -93,7 +93,8 @@ config SYSCTL
limited in memory.
config LOG_BUF_SHIFT
- int "Kernel log buffer size" if DEBUG_KERNEL
+ int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" if DEBUG_KERNEL
+ range 12 20
default 17 if ARCH_S390
default 16 if X86_NUMAQ || IA64
default 15 if SMP
diff --git a/ipc/sem.c b/ipc/sem.c
index 07d9a2e054b7..d1a54864f753 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -49,6 +49,10 @@
* increase. If there are decrement operations in the operations
* array we do the same as before.
*
+ * With the incarnation of O(1) scheduler, it becomes unnecessary to perform
+ * check/retry algorithm for waking up blocked processes as the new scheduler
+ * is better at handling thread switch than the old one.
+ *
* /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
*
* SMP-threaded, sysctl's added
@@ -258,8 +262,7 @@ static inline void remove_from_queue (struct sem_array * sma,
*/
static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
- int nsops, struct sem_undo *un, int pid,
- int do_undo)
+ int nsops, struct sem_undo *un, int pid)
{
int result, sem_op;
struct sembuf *sop;
@@ -289,10 +292,6 @@ static int try_atomic_semop (struct sem_array * sma, struct sembuf * sops,
curr->semval = result;
}
- if (do_undo) {
- result = 0;
- goto undo;
- }
sop--;
while (sop >= sops) {
sma->sem_base[sop->sem_num].sempid = pid;
@@ -334,23 +333,14 @@ static void update_queue (struct sem_array * sma)
for (q = sma->sem_pending; q; q = q->next) {
- if (q->status == 1)
- continue; /* this one was woken up before */
-
error = try_atomic_semop(sma, q->sops, q->nsops,
- q->undo, q->pid, q->alter);
+ q->undo, q->pid);
/* Does q->sleeper still need to sleep? */
if (error <= 0) {
- /* Found one, wake it up */
- wake_up_process(q->sleeper);
- if (error == 0 && q->alter) {
- /* if q-> alter let it self try */
- q->status = 1;
- return;
- }
q->status = error;
remove_from_queue(sma,q);
+ wake_up_process(q->sleeper);
}
}
}
@@ -1062,7 +1052,7 @@ retry_undos:
if (error)
goto out_unlock_free;
- error = try_atomic_semop (sma, sops, nsops, un, current->pid, 0);
+ error = try_atomic_semop (sma, sops, nsops, un, current->pid);
if (error <= 0)
goto update;
@@ -1075,55 +1065,46 @@ retry_undos:
queue.nsops = nsops;
queue.undo = un;
queue.pid = current->pid;
- queue.alter = decrease;
queue.id = semid;
if (alter)
append_to_queue(sma ,&queue);
else
prepend_to_queue(sma ,&queue);
- for (;;) {
- queue.status = -EINTR;
- queue.sleeper = current;
- current->state = TASK_INTERRUPTIBLE;
- sem_unlock(sma);
+ queue.status = -EINTR;
+ queue.sleeper = current;
+ current->state = TASK_INTERRUPTIBLE;
+ sem_unlock(sma);
- if (timeout)
- jiffies_left = schedule_timeout(jiffies_left);
- else
- schedule();
+ if (timeout)
+ jiffies_left = schedule_timeout(jiffies_left);
+ else
+ schedule();
- sma = sem_lock(semid);
- if(sma==NULL) {
- if(queue.prev != NULL)
- BUG();
- error = -EIDRM;
- goto out_free;
- }
- /*
- * If queue.status == 1 we where woken up and
- * have to retry else we simply return.
- * If an interrupt occurred we have to clean up the
- * queue
- *
- */
- if (queue.status == 1)
- {
- error = try_atomic_semop (sma, sops, nsops, un,
- current->pid,0);
- if (error <= 0)
- break;
- } else {
- error = queue.status;
- if (error == -EINTR && timeout && jiffies_left == 0)
- error = -EAGAIN;
- if (queue.prev) /* got Interrupt */
- break;
- /* Everything done by update_queue */
- goto out_unlock_free;
- }
+ sma = sem_lock(semid);
+ if(sma==NULL) {
+ if(queue.prev != NULL)
+ BUG();
+ error = -EIDRM;
+ goto out_free;
+ }
+
+ /*
+ * If queue.status != -EINTR we are woken up by another process
+ */
+ error = queue.status;
+ if (queue.status != -EINTR) {
+ goto out_unlock_free;
}
+
+ /*
+ * If an interrupt occurred we have to clean up the queue
+ */
+ if (timeout && jiffies_left == 0)
+ error = -EAGAIN;
remove_from_queue(sma,&queue);
+ goto out_unlock_free;
+
update:
if (alter)
update_queue (sma);
diff --git a/kernel/acct.c b/kernel/acct.c
index e63095525ac2..0009dfb25dcb 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -394,17 +394,25 @@ static void do_acct_process(long exitcode, struct file *file)
/*
* acct_process - now just a wrapper around do_acct_process
*/
-int acct_process(long exitcode)
+void acct_process(long exitcode)
{
struct file *file = NULL;
+
+ /*
+ * accelerate the common fastpath:
+ */
+ if (!acct_globals.file)
+ return;
+
spin_lock(&acct_globals.lock);
- if (acct_globals.file) {
- file = acct_globals.file;
- get_file(file);
+ file = acct_globals.file;
+ if (unlikely(!file)) {
spin_unlock(&acct_globals.lock);
- do_acct_process(exitcode, file);
- fput(file);
- } else
- spin_unlock(&acct_globals.lock);
- return 0;
+ return;
+ }
+ get_file(file);
+ spin_unlock(&acct_globals.lock);
+
+ do_acct_process(exitcode, file);
+ fput(file);
}
diff --git a/kernel/exit.c b/kernel/exit.c
index 367854d246ef..7792bb1268ff 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -230,6 +230,7 @@ void reparent_to_init(void)
/* signals? */
security_task_reparent_to_init(current);
memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
+ atomic_inc(&(INIT_USER->__count));
switch_uid(INIT_USER);
write_unlock_irq(&tasklist_lock);
@@ -442,7 +443,7 @@ static inline void __exit_mm(struct task_struct * tsk)
/* more a memory barrier than a real lock */
task_lock(tsk);
tsk->mm = NULL;
- enter_lazy_tlb(mm, current, smp_processor_id());
+ enter_lazy_tlb(mm, current);
task_unlock(tsk);
mmput(mm);
}
@@ -651,6 +652,8 @@ static void exit_notify(struct task_struct *tsk)
if (tsk->exit_signal != -1) {
int signal = tsk->parent == tsk->real_parent ? tsk->exit_signal : SIGCHLD;
do_notify_parent(tsk, signal);
+ } else if (tsk->ptrace) {
+ do_notify_parent(tsk, SIGCHLD);
}
tsk->state = TASK_ZOMBIE;
@@ -680,6 +683,8 @@ NORET_TYPE void do_exit(long code)
panic("Attempted to kill the idle task!");
if (unlikely(tsk->pid == 1))
panic("Attempted to kill init!");
+ if (tsk->io_context)
+ exit_io_context();
tsk->flags |= PF_EXITING;
del_timer_sync(&tsk->real_timer);
@@ -715,7 +720,7 @@ NORET_TYPE void do_exit(long code)
tsk->exit_code = code;
exit_notify(tsk);
- if (tsk->exit_signal == -1)
+ if (tsk->exit_signal == -1 && tsk->ptrace == 0)
release_task(tsk);
schedule();
@@ -859,7 +864,7 @@ static int wait_task_zombie(task_t *p, unsigned int *stat_addr, struct rusage *r
BUG_ON(state != TASK_DEAD);
return 0;
}
- if (unlikely(p->exit_signal == -1))
+ if (unlikely(p->exit_signal == -1 && p->ptrace == 0))
/*
* This can only happen in a race with a ptraced thread
* dying on another processor.
@@ -889,8 +894,12 @@ static int wait_task_zombie(task_t *p, unsigned int *stat_addr, struct rusage *r
/* Double-check with lock held. */
if (p->real_parent != p->parent) {
__ptrace_unlink(p);
- do_notify_parent(p, p->exit_signal);
p->state = TASK_ZOMBIE;
+ /* If this is a detached thread, this is where it goes away. */
+ if (p->exit_signal == -1)
+ release_task (p);
+ else
+ do_notify_parent(p, p->exit_signal);
p = NULL;
}
write_unlock_irq(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index 2abbc9c2da23..96ce3385cc75 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -286,7 +286,7 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
continue;
if (mpnt->vm_flags & VM_ACCOUNT) {
unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
- if (!vm_enough_memory(len))
+ if (security_vm_enough_memory(len))
goto fail_nomem;
charge += len;
}
@@ -864,6 +864,7 @@ struct task_struct *copy_process(unsigned long clone_flags,
p->lock_depth = -1; /* -1 = no lock */
p->start_time = get_jiffies_64();
p->security = NULL;
+ p->io_context = NULL;
retval = -ENOMEM;
if ((retval = security_task_alloc(p)))
diff --git a/kernel/ksyms.c b/kernel/ksyms.c
index 8544287c9045..66ea4b6b4d84 100644
--- a/kernel/ksyms.c
+++ b/kernel/ksyms.c
@@ -462,6 +462,7 @@ EXPORT_SYMBOL(preempt_schedule);
#endif
EXPORT_SYMBOL(schedule_timeout);
EXPORT_SYMBOL(yield);
+EXPORT_SYMBOL(io_schedule);
EXPORT_SYMBOL(__cond_resched);
EXPORT_SYMBOL(set_user_nice);
EXPORT_SYMBOL(task_nice);
@@ -586,7 +587,7 @@ EXPORT_SYMBOL(tasklet_kill);
EXPORT_SYMBOL(do_softirq);
EXPORT_SYMBOL(raise_softirq);
EXPORT_SYMBOL(open_softirq);
-EXPORT_SYMBOL(cpu_raise_softirq);
+EXPORT_SYMBOL(raise_softirq_irqoff);
EXPORT_SYMBOL(__tasklet_schedule);
EXPORT_SYMBOL(__tasklet_hi_schedule);
diff --git a/kernel/sched.c b/kernel/sched.c
index bb552059577d..556c5cdbb9c2 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -508,8 +508,8 @@ repeat_lock_task:
}
#ifdef CONFIG_SMP
else
- if (unlikely(kick) && task_running(rq, p) && (p->thread_info->cpu != smp_processor_id()))
- smp_send_reschedule(p->thread_info->cpu);
+ if (unlikely(kick) && task_running(rq, p) && (task_cpu(p) != smp_processor_id()))
+ smp_send_reschedule(task_cpu(p));
#endif
p->state = TASK_RUNNING;
}
@@ -646,9 +646,9 @@ static inline task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next
if (unlikely(!mm)) {
next->active_mm = oldmm;
atomic_inc(&oldmm->mm_count);
- enter_lazy_tlb(oldmm, next, smp_processor_id());
+ enter_lazy_tlb(oldmm, next);
} else
- switch_mm(oldmm, mm, next, smp_processor_id());
+ switch_mm(oldmm, mm, next);
if (unlikely(!prev->mm)) {
prev->active_mm = NULL;
@@ -1175,6 +1175,7 @@ DEFINE_PER_CPU(struct kernel_stat, kstat) = { { 0 } };
void scheduler_tick(int user_ticks, int sys_ticks)
{
int cpu = smp_processor_id();
+ struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat;
runqueue_t *rq = this_rq();
task_t *p = current;
@@ -1184,19 +1185,19 @@ void scheduler_tick(int user_ticks, int sys_ticks)
if (p == rq->idle) {
/* note: this timer irq context must be accounted for as well */
if (irq_count() - HARDIRQ_OFFSET >= SOFTIRQ_OFFSET)
- kstat_cpu(cpu).cpustat.system += sys_ticks;
+ cpustat->system += sys_ticks;
else if (atomic_read(&rq->nr_iowait) > 0)
- kstat_cpu(cpu).cpustat.iowait += sys_ticks;
+ cpustat->iowait += sys_ticks;
else
- kstat_cpu(cpu).cpustat.idle += sys_ticks;
+ cpustat->idle += sys_ticks;
rebalance_tick(rq, 1);
return;
}
if (TASK_NICE(p) > 0)
- kstat_cpu(cpu).cpustat.nice += user_ticks;
+ cpustat->nice += user_ticks;
else
- kstat_cpu(cpu).cpustat.user += user_ticks;
- kstat_cpu(cpu).cpustat.system += sys_ticks;
+ cpustat->user += user_ticks;
+ cpustat->system += sys_ticks;
/* Task might have expired already, but not scheduled off yet */
if (p->array != rq->active) {
@@ -1332,7 +1333,7 @@ pick_next_task:
switch_tasks:
prefetch(next);
clear_tsk_need_resched(prev);
- RCU_qsctr(prev->thread_info->cpu)++;
+ RCU_qsctr(task_cpu(prev))++;
if (likely(prev != next)) {
rq->nr_switches++;
@@ -2527,7 +2528,7 @@ void __init sched_init(void)
* The boot idle thread does lazy MMU switching as well:
*/
atomic_inc(&init_mm.mm_count);
- enter_lazy_tlb(&init_mm, current, smp_processor_id());
+ enter_lazy_tlb(&init_mm, current);
}
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
diff --git a/kernel/signal.c b/kernel/signal.c
index 78c4dfa0073c..7ac72191b30b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -579,8 +579,8 @@ static int rm_from_queue(unsigned long mask, struct sigpending *s)
/*
* Bad permissions for sending the signal
*/
-static inline int check_kill_permission(int sig, struct siginfo *info,
- struct task_struct *t)
+static int check_kill_permission(int sig, struct siginfo *info,
+ struct task_struct *t)
{
int error = -EINVAL;
if (sig < 0 || sig > _NSIG)
@@ -797,10 +797,11 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
int ret;
spin_lock_irqsave(&t->sighand->siglock, flags);
- if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN)
+ if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
- sigdelset(&t->blocked, sig);
- recalc_sigpending_tsk(t);
+ sigdelset(&t->blocked, sig);
+ recalc_sigpending_tsk(t);
+ }
ret = specific_send_sig_info(sig, info, t);
spin_unlock_irqrestore(&t->sighand->siglock, flags);
@@ -2081,12 +2082,58 @@ sys_kill(int pid, int sig)
info.si_signo = sig;
info.si_errno = 0;
info.si_code = SI_USER;
- info.si_pid = current->pid;
+ info.si_pid = current->tgid;
info.si_uid = current->uid;
return kill_something_info(sig, &info, pid);
}
+/**
+ * sys_tkill - send signal to one specific thread
+ * @tgid: the thread group ID of the thread
+ * @pid: the PID of the thread
+ * @sig: signal to be sent
+ *
+ * This syscall also checks the tgid and returns -ESRCH even if the PID
+ * exists but it's not belonging to the target process anymore. This
+ * method solves the problem of threads exiting and PIDs getting reused.
+ */
+asmlinkage long sys_tgkill(int tgid, int pid, int sig)
+{
+ struct siginfo info;
+ int error;
+ struct task_struct *p;
+
+ /* This is only valid for single tasks */
+ if (pid <= 0 || tgid <= 0)
+ return -EINVAL;
+
+ info.si_signo = sig;
+ info.si_errno = 0;
+ info.si_code = SI_TKILL;
+ info.si_pid = current->tgid;
+ info.si_uid = current->uid;
+
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ error = -ESRCH;
+ if (p && (p->tgid == tgid)) {
+ error = check_kill_permission(sig, &info, p);
+ /*
+ * The null signal is a permissions and process existence
+ * probe. No signal is actually delivered.
+ */
+ if (!error && sig && p->sighand) {
+ spin_lock_irq(&p->sighand->siglock);
+ handle_stop_signal(sig, p);
+ error = specific_send_sig_info(sig, &info, p);
+ spin_unlock_irq(&p->sighand->siglock);
+ }
+ }
+ read_unlock(&tasklist_lock);
+ return error;
+}
+
/*
* Send a signal to only one task, even if it's a CLONE_THREAD task.
*/
@@ -2104,7 +2151,7 @@ sys_tkill(int pid, int sig)
info.si_signo = sig;
info.si_errno = 0;
info.si_code = SI_TKILL;
- info.si_pid = current->pid;
+ info.si_pid = current->tgid;
info.si_uid = current->uid;
read_lock(&tasklist_lock);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 20bf233a14c3..96294a3d673f 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/notifier.h>
+#include <linux/percpu.h>
#include <linux/cpu.h>
/*
@@ -41,15 +42,18 @@ EXPORT_SYMBOL(irq_stat);
static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
+static DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+
/*
* we cannot loop indefinitely here to avoid userspace starvation,
* but we also don't want to introduce a worst case 1/HZ latency
* to the pending events, so lets the scheduler to balance
* the softirq load for us.
*/
-static inline void wakeup_softirqd(unsigned cpu)
+static inline void wakeup_softirqd(void)
{
- struct task_struct * tsk = ksoftirqd_task(cpu);
+ /* Interrupts are disabled: no need to stop preemption */
+ struct task_struct *tsk = __get_cpu_var(ksoftirqd);
if (tsk && tsk->state != TASK_RUNNING)
wake_up_process(tsk);
@@ -96,7 +100,7 @@ restart:
goto restart;
}
if (pending)
- wakeup_softirqd(smp_processor_id());
+ wakeup_softirqd();
__local_bh_enable();
}
@@ -117,9 +121,9 @@ EXPORT_SYMBOL(local_bh_enable);
/*
* This function must run with irqs disabled!
*/
-inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
+inline void raise_softirq_irqoff(unsigned int nr)
{
- __cpu_raise_softirq(cpu, nr);
+ __raise_softirq_irqoff(nr);
/*
* If we're in an interrupt or softirq, we're done
@@ -131,7 +135,7 @@ inline void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
* schedule the softirq soon.
*/
if (!in_interrupt())
- wakeup_softirqd(cpu);
+ wakeup_softirqd();
}
void raise_softirq(unsigned int nr)
@@ -139,7 +143,7 @@ void raise_softirq(unsigned int nr)
unsigned long flags;
local_irq_save(flags);
- cpu_raise_softirq(smp_processor_id(), nr);
+ raise_softirq_irqoff(nr);
local_irq_restore(flags);
}
@@ -168,7 +172,7 @@ void __tasklet_schedule(struct tasklet_struct *t)
local_irq_save(flags);
t->next = __get_cpu_var(tasklet_vec).list;
__get_cpu_var(tasklet_vec).list = t;
- cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ);
+ raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_restore(flags);
}
@@ -179,7 +183,7 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
local_irq_save(flags);
t->next = __get_cpu_var(tasklet_hi_vec).list;
__get_cpu_var(tasklet_hi_vec).list = t;
- cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ);
+ raise_softirq_irqoff(HI_SOFTIRQ);
local_irq_restore(flags);
}
@@ -211,7 +215,7 @@ static void tasklet_action(struct softirq_action *a)
local_irq_disable();
t->next = __get_cpu_var(tasklet_vec).list;
__get_cpu_var(tasklet_vec).list = t;
- __cpu_raise_softirq(smp_processor_id(), TASKLET_SOFTIRQ);
+ __raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}
@@ -244,7 +248,7 @@ static void tasklet_hi_action(struct softirq_action *a)
local_irq_disable();
t->next = __get_cpu_var(tasklet_hi_vec).list;
__get_cpu_var(tasklet_hi_vec).list = t;
- __cpu_raise_softirq(smp_processor_id(), HI_SOFTIRQ);
+ __raise_softirq_irqoff(HI_SOFTIRQ);
local_irq_enable();
}
}
@@ -325,7 +329,7 @@ static int ksoftirqd(void * __bind_cpu)
__set_current_state(TASK_INTERRUPTIBLE);
mb();
- local_ksoftirqd_task() = current;
+ __get_cpu_var(ksoftirqd) = current;
for (;;) {
if (!local_softirq_pending())
@@ -354,7 +358,7 @@ static int __devinit cpu_callback(struct notifier_block *nfb,
return NOTIFY_BAD;
}
- while (!ksoftirqd_task(hotcpu))
+ while (!per_cpu(ksoftirqd, hotcpu))
yield();
}
return NOTIFY_OK;
diff --git a/kernel/suspend.c b/kernel/suspend.c
index 843cbaf6d433..1033ee31df68 100644
--- a/kernel/suspend.c
+++ b/kernel/suspend.c
@@ -1203,12 +1203,12 @@ static int read_suspend_image(const char * specialfile, int noresume)
void software_resume(void)
{
-#ifdef CONFIG_SMP
- printk(KERN_WARNING "Software Suspend has a malfunctioning SMP support. Disabled :(\n");
-#else
+ if (num_online_cpus() > 1) {
+ printk(KERN_WARNING "Software Suspend has malfunctioning SMP support. Disabled :(\n");
+ return;
+ }
/* We enable the possibility of machine suspend */
software_suspend_enabled = 1;
-#endif
if (!resume_status)
return;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 7f0cc00cfa4d..edebad7ddec4 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -130,7 +130,7 @@ extern ctl_table random_table[];
static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_sys_permission(struct inode *, int);
+static int proc_sys_permission(struct inode *, int, struct nameidata *);
struct file_operations proc_sys_file_operations = {
.read = proc_readsys,
@@ -1177,7 +1177,7 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
return do_rw_proc(1, file, (char __user *) buf, count, ppos);
}
-static int proc_sys_permission(struct inode *inode, int op)
+static int proc_sys_permission(struct inode *inode, int op, struct nameidata *nd)
{
return test_perm(inode->i_mode, op);
}
diff --git a/kernel/timer.c b/kernel/timer.c
index 7bce7a7cb2c2..3995425e44a5 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -126,13 +126,17 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
* or you set a timer to go off in the past
*/
vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
- } else if (idx <= 0xffffffffUL) {
- int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
- vec = base->tv5.vec + i;
} else {
- /* Can only get here on architectures with 64-bit jiffies */
- INIT_LIST_HEAD(&timer->entry);
- return;
+ int i;
+ /* If the timeout is larger than 0xffffffff on 64-bit
+ * architectures then we use the maximum timeout:
+ */
+ if (idx > 0xffffffffUL) {
+ idx = 0xffffffffUL;
+ expires = idx + base->timer_jiffies;
+ }
+ i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
+ vec = base->tv5.vec + i;
}
/*
* Timers are FIFO:
diff --git a/kernel/user.c b/kernel/user.c
index 592680d8cc68..86bd412b85da 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -126,7 +126,6 @@ void switch_uid(struct user_struct *new_user)
* we should be checking for it. -DaveM
*/
old_user = current->user;
- atomic_inc(&new_user->__count);
atomic_inc(&new_user->processes);
atomic_dec(&old_user->processes);
current->user = new_user;
diff --git a/lib/Makefile b/lib/Makefile
index 9121869155a6..91e7b30d3ca0 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,7 +5,7 @@
lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
- kobject.o idr.o
+ kobject.o idr.o div64.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
diff --git a/lib/div64.c b/lib/div64.c
new file mode 100644
index 000000000000..eab47437f182
--- /dev/null
+++ b/lib/div64.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
+ *
+ * Based on former do_div() implementation from asm-parisc/div64.h:
+ * Copyright (C) 1999 Hewlett-Packard Co
+ * Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ *
+ * Generic C version of 64bit/32bit division and modulo, with
+ * 64bit result and 32bit remainder.
+ *
+ * The fast case for (n>>32 == 0) is handled inline by do_div().
+ *
+ * Code generated for this function might be very inefficient
+ * for some CPUs. div64_32() can be overridden by linking arch-specific
+ * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S.
+ */
+
+#include <linux/types.h>
+#include <asm/div64.h>
+
+uint32_t __div64_32(uint64_t *n, uint32_t base)
+{
+ uint32_t low, low2, high, rem;
+
+ low = *n & 0xffffffff;
+ high = *n >> 32;
+ rem = high % (uint32_t)base;
+ high = high / (uint32_t)base;
+ low2 = low >> 16;
+ low2 += rem << 16;
+ rem = low2 % (uint32_t)base;
+ low2 = low2 / (uint32_t)base;
+ low = low & 0xffff;
+ low += rem << 16;
+ rem = low % (uint32_t)base;
+ low = low / (uint32_t)base;
+
+ *n = low +
+ ((uint64_t)low2 << 16) +
+ ((uint64_t)high << 32);
+
+ return rem;
+}
+
diff --git a/lib/kobject.c b/lib/kobject.c
index fb49131f5ff9..15fa0ba4dd88 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -314,6 +314,21 @@ int kobject_register(struct kobject * kobj)
}
/**
+ * kobject_rename - change the name of an object
+ * @kobj: object in question.
+ * @new_name: object's new name
+ */
+
+void kobject_rename(struct kobject * kobj, char *new_name)
+{
+ kobj = kobject_get(kobj);
+ if (!kobj)
+ return;
+ sysfs_rename_dir(kobj, new_name);
+ kobject_put(kobj);
+}
+
+/**
* kobject_del - unlink kobject from hierarchy.
* @kobj: object.
*/
diff --git a/mm/bootmem.c b/mm/bootmem.c
index db4aff37a1a9..48f286bb780a 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -84,10 +84,6 @@ static void __init reserve_bootmem_core(bootmem_data_t *bdata, unsigned long add
if (!size) BUG();
- if (sidx < 0)
- BUG();
- if (eidx < 0)
- BUG();
if (sidx >= eidx)
BUG();
if ((addr >> PAGE_SHIFT) >= bdata->node_low_pfn)
@@ -202,7 +198,7 @@ restart_scan:
;
}
- if (preferred) {
+ if (preferred > offset) {
preferred = offset;
goto restart_scan;
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 1352d59d2ee4..f9623a9fecc6 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -925,6 +925,9 @@ static int page_cache_read(struct file * file, unsigned long offset)
return error == -EEXIST ? 0 : error;
}
+#define MMAP_READAROUND (16UL)
+#define MMAP_LOTSAMISS (100)
+
/*
* filemap_nopage() is invoked via the vma operations vector for a
* mapped memory region to read in file data during a page fault.
@@ -942,19 +945,19 @@ struct page * filemap_nopage(struct vm_area_struct * area, unsigned long address
struct inode *inode = mapping->host;
struct page *page;
unsigned long size, pgoff, endoff;
- int did_readahead;
+ int did_readaround = 0;
pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT) + area->vm_pgoff;
retry_all:
- /*
- * An external ptracer can access pages that normally aren't
- * accessible..
- */
size = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
- if ((pgoff >= size) && (area->vm_mm == current->mm))
- return NULL;
+ if (pgoff >= size)
+ goto outside_data_content;
+
+ /* If we don't want any read-ahead, don't bother */
+ if (VM_RandomReadHint(area))
+ goto no_cached_page;
/*
* The "size" of the file, as far as mmap is concerned, isn't bigger
@@ -963,25 +966,14 @@ retry_all:
if (size > endoff)
size = endoff;
- did_readahead = 0;
-
/*
* The readahead code wants to be told about each and every page
* so it can build and shrink its windows appropriately
+ *
+ * For sequential accesses, we use the generic readahead logic.
*/
- if (VM_SequentialReadHint(area)) {
- did_readahead = 1;
+ if (VM_SequentialReadHint(area))
page_cache_readahead(mapping, ra, file, pgoff);
- }
-
- /*
- * If the offset is outside the mapping size we're off the end
- * of a privately mapped file, so we need to map a zero page.
- */
- if ((pgoff < size) && !VM_RandomReadHint(area)) {
- did_readahead = 1;
- page_cache_readaround(mapping, ra, file, pgoff);
- }
/*
* Do we have something in the page cache already?
@@ -989,13 +981,27 @@ retry_all:
retry_find:
page = find_get_page(mapping, pgoff);
if (!page) {
- if (did_readahead) {
+ if (VM_SequentialReadHint(area)) {
handle_ra_miss(mapping, ra, pgoff);
- did_readahead = 0;
+ goto no_cached_page;
}
- goto no_cached_page;
+ ra->mmap_miss++;
+
+ /*
+ * Do we miss much more than hit in this file? If so,
+ * stop bothering with read-ahead. It will only hurt.
+ */
+ if (ra->mmap_miss > ra->mmap_hit + MMAP_LOTSAMISS)
+ goto no_cached_page;
+
+ did_readaround = 1;
+ do_page_cache_readahead(mapping, file, pgoff & ~(MMAP_READAROUND-1), MMAP_READAROUND);
+ goto retry_find;
}
+ if (!did_readaround)
+ ra->mmap_hit++;
+
/*
* Ok, found a page in the page cache, now we need to check
* that it's up-to-date.
@@ -1010,6 +1016,14 @@ success:
mark_page_accessed(page);
return page;
+outside_data_content:
+ /*
+ * An external ptracer can access pages that normally aren't
+ * accessible..
+ */
+ if (area->vm_mm == current->mm)
+ return NULL;
+ /* Fall through to the non-read-ahead case */
no_cached_page:
/*
* We're only likely to ever get here if MADV_RANDOM is in
diff --git a/mm/mmap.c b/mm/mmap.c
index c83cf2a8b126..1052f84a82a2 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -18,6 +18,7 @@
#include <linux/security.h>
#include <linux/hugetlb.h>
#include <linux/profile.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -53,65 +54,9 @@ int sysctl_overcommit_memory = 0; /* default is heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
atomic_t vm_committed_space = ATOMIC_INIT(0);
-/*
- * Check that a process has enough memory to allocate a new virtual
- * mapping. 1 means there is enough memory for the allocation to
- * succeed and 0 implies there is not.
- *
- * We currently support three overcommit policies, which are set via the
- * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-acounting
- *
- * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
- * Additional code 2002 Jul 20 by Robert Love.
- */
-extern atomic_t slab_reclaim_pages;
-int vm_enough_memory(long pages)
-{
- unsigned long free, allowed;
-
- vm_acct_memory(pages);
-
- /*
- * Sometimes we want to use more memory than we have
- */
- if (sysctl_overcommit_memory == 1)
- return 1;
-
- if (sysctl_overcommit_memory == 0) {
- free = get_page_cache_size();
- free += nr_free_pages();
- free += nr_swap_pages;
-
- /*
- * Any slabs which are created with the
- * SLAB_RECLAIM_ACCOUNT flag claim to have contents
- * which are reclaimable, under pressure. The dentry
- * cache and most inode caches should fall into this
- */
- free += atomic_read(&slab_reclaim_pages);
-
- /*
- * Leave the last 3% for root
- */
- if (!capable(CAP_SYS_ADMIN))
- free -= free / 32;
-
- if (free > pages)
- return 1;
- vm_unacct_memory(pages);
- return 0;
- }
-
- allowed = totalram_pages * sysctl_overcommit_ratio / 100;
- allowed += total_swap_pages;
-
- if (atomic_read(&vm_committed_space) < allowed)
- return 1;
-
- vm_unacct_memory(pages);
-
- return 0;
-}
+EXPORT_SYMBOL(sysctl_overcommit_memory);
+EXPORT_SYMBOL(sysctl_overcommit_ratio);
+EXPORT_SYMBOL(vm_committed_space);
/*
* Requires inode->i_mapping->i_shared_sem
@@ -646,7 +591,7 @@ munmap_back:
* Private writable mapping: check memory availability
*/
charged = len >> PAGE_SHIFT;
- if (!vm_enough_memory(charged))
+ if (security_vm_enough_memory(charged))
return -ENOMEM;
vm_flags |= VM_ACCOUNT;
}
@@ -950,7 +895,7 @@ int expand_stack(struct vm_area_struct * vma, unsigned long address)
grow = (address - vma->vm_end) >> PAGE_SHIFT;
/* Overcommit.. */
- if (!vm_enough_memory(grow)) {
+ if (security_vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM;
}
@@ -1004,7 +949,7 @@ int expand_stack(struct vm_area_struct *vma, unsigned long address)
grow = (vma->vm_start - address) >> PAGE_SHIFT;
/* Overcommit.. */
- if (!vm_enough_memory(grow)) {
+ if (security_vm_enough_memory(grow)) {
spin_unlock(&vma->vm_mm->page_table_lock);
return -ENOMEM;
}
@@ -1376,7 +1321,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
if (mm->map_count > MAX_MAP_COUNT)
return -ENOMEM;
- if (!vm_enough_memory(len >> PAGE_SHIFT))
+ if (security_vm_enough_memory(len >> PAGE_SHIFT))
return -ENOMEM;
flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 978a9509c350..2c015794e3c1 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -175,7 +175,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
if (newflags & VM_WRITE) {
if (!(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
charged = (end - start) >> PAGE_SHIFT;
- if (!vm_enough_memory(charged))
+ if (security_vm_enough_memory(charged))
return -ENOMEM;
newflags |= VM_ACCOUNT;
}
diff --git a/mm/mremap.c b/mm/mremap.c
index 8c6ec8b926d4..088af945ac5e 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -16,6 +16,7 @@
#include <linux/fs.h>
#include <linux/highmem.h>
#include <linux/rmap-locking.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -244,9 +245,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
}
if (!move_page_tables(vma, new_addr, addr, old_len)) {
- unsigned long must_fault_in;
- unsigned long fault_in_start;
- unsigned long fault_in_end;
+ unsigned long vm_locked = vma->vm_flags & VM_LOCKED;
if (allocated_vma) {
*new_vma = *vma;
@@ -272,14 +271,8 @@ static unsigned long move_vma(struct vm_area_struct *vma,
} else
vma = NULL; /* nothing more to do */
- must_fault_in = new_vma->vm_flags & VM_LOCKED;
- fault_in_start = new_vma->vm_start;
- fault_in_end = new_vma->vm_end;
-
do_munmap(current->mm, addr, old_len);
- /* new_vma could have been invalidated by do_munmap */
-
/* Restore VM_ACCOUNT if one or two pieces of vma left */
if (vma) {
vma->vm_flags |= VM_ACCOUNT;
@@ -288,9 +281,11 @@ static unsigned long move_vma(struct vm_area_struct *vma,
}
current->mm->total_vm += new_len >> PAGE_SHIFT;
- if (must_fault_in) {
+ if (vm_locked) {
current->mm->locked_vm += new_len >> PAGE_SHIFT;
- make_pages_present(fault_in_start, fault_in_end);
+ if (new_len > old_len)
+ make_pages_present(new_addr + old_len,
+ new_addr + new_len);
}
return new_addr;
}
@@ -391,7 +386,7 @@ unsigned long do_mremap(unsigned long addr,
if (vma->vm_flags & VM_ACCOUNT) {
charged = (new_len - old_len) >> PAGE_SHIFT;
- if (!vm_enough_memory(charged))
+ if (security_vm_enough_memory(charged))
goto out_nc;
}
diff --git a/mm/nommu.c b/mm/nommu.c
index cd7900bf3fe8..5595fa7054f8 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -62,11 +62,8 @@ do_expand:
inode->i_size = offset;
out_truncate:
- if (inode->i_op && inode->i_op->truncate) {
- lock_kernel();
+ if (inode->i_op && inode->i_op->truncate)
inode->i_op->truncate(inode);
- unlock_kernel();
- }
return 0;
out_sig:
send_sig(SIGXFSZ, current, 0);
@@ -253,23 +250,16 @@ static inline unsigned long calc_vm_flags(unsigned long prot, unsigned long flag
#ifdef DEBUG
static void show_process_blocks(void)
{
- struct mm_tblock_struct * tblock, *tmp;
-
+ struct mm_tblock_struct *tblock;
+
printk("Process blocks %d:", current->pid);
-
- tmp = current->mm->context.tblock;
- while (tmp) {
- printk(" %p: %p", tmp, tmp->rblock);
- if (tmp->rblock)
- printk(" (%d @%p #%d)", kobjsize(tmp->rblock->kblock),
- tmp->rblock->kblock, tmp->rblock->refcount);
- if (tmp->next)
- printk(" ->");
- else
- printk(".");
- tmp = tmp->next;
+
+ for (tblock = &current->mm->context.tblock; tblock; tblock = tblock->next) {
+ printk(" %p: %p", tblock, tblock->rblock);
+ if (tblock->rblock)
+ printk(" (%d @%p #%d)", kobjsize(tblock->rblock->kblock), tblock->rblock->kblock, tblock->rblock->refcount);
+ printk(tblock->next ? " ->" : ".\n");
}
- printk("\n");
}
#endif /* DEBUG */
@@ -358,7 +348,7 @@ unsigned long do_mmap_pgoff(
error = file->f_op->mmap(file, &vma);
#ifdef DEBUG
- printk("mmap mmap returned %d /%x\n", error, vma.vm_start);
+ printk("f_op->mmap() returned %d/%lx\n", error, vma.vm_start);
#endif
if (!error)
return vma.vm_start;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dfd254c2c94b..16077203e5a4 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -32,6 +32,8 @@
#include <linux/sysctl.h>
#include <linux/cpu.h>
+#include <asm/tlbflush.h>
+
DECLARE_BITMAP(node_online_map, MAX_NUMNODES);
DECLARE_BITMAP(memblk_online_map, MAX_NR_MEMBLKS);
struct pglist_data *pgdat_list;
@@ -41,6 +43,9 @@ int nr_swap_pages;
int numnodes = 1;
int sysctl_lower_zone_protection = 0;
+EXPORT_SYMBOL(totalram_pages);
+EXPORT_SYMBOL(nr_swap_pages);
+
/*
* Used by page_zone() to look up the address of the struct zone whose
* id is encoded in the upper bits of page->flags
@@ -265,6 +270,7 @@ void __free_pages_ok(struct page *page, unsigned int order)
mod_page_state(pgfree, 1 << order);
free_pages_check(__FUNCTION__, page);
list_add(&page->list, &list);
+ kernel_map_pages(page, 1<<order, 0);
free_pages_bulk(page_zone(page), 1, &list, order);
}
@@ -440,6 +446,7 @@ static void free_hot_cold_page(struct page *page, int cold)
struct per_cpu_pages *pcp;
unsigned long flags;
+ kernel_map_pages(page, 1, 0);
inc_page_state(pgfree);
free_pages_check(__FUNCTION__, page);
pcp = &zone->pageset[get_cpu()].pcp[cold];
@@ -556,7 +563,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, cold);
if (page)
- return page;
+ goto got_pg;
}
min += z->pages_low * sysctl_lower_zone_protection;
}
@@ -579,7 +586,7 @@ __alloc_pages(unsigned int gfp_mask, unsigned int order,
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, cold);
if (page)
- return page;
+ goto got_pg;
}
min += local_min * sysctl_lower_zone_protection;
}
@@ -594,7 +601,7 @@ rebalance:
page = buffered_rmqueue(z, order, cold);
if (page)
- return page;
+ goto got_pg;
}
goto nopage;
}
@@ -622,7 +629,7 @@ rebalance:
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, cold);
if (page)
- return page;
+ goto got_pg;
}
min += z->pages_low * sysctl_lower_zone_protection;
}
@@ -653,6 +660,9 @@ nopage:
current->comm, order, gfp_mask);
}
return NULL;
+got_pg:
+ kernel_map_pages(page, 1 << order, 1);
+ return page;
}
/*
@@ -726,6 +736,7 @@ unsigned int nr_free_pages(void)
return sum;
}
+EXPORT_SYMBOL(nr_free_pages);
unsigned int nr_used_zone_pages(void)
{
@@ -818,6 +829,7 @@ DEFINE_PER_CPU(struct page_state, page_states) = {0};
EXPORT_PER_CPU_SYMBOL(page_states);
atomic_t nr_pagecache = ATOMIC_INIT(0);
+EXPORT_SYMBOL(nr_pagecache);
#ifdef CONFIG_SMP
DEFINE_PER_CPU(long, nr_pagecache_local) = 0;
#endif
@@ -896,7 +908,7 @@ void si_meminfo_node(struct sysinfo *val, int nid)
{
pg_data_t *pgdat = NODE_DATA(nid);
- val->totalram = pgdat->node_size;
+ val->totalram = pgdat->node_present_pages;
val->freeram = nr_free_pages_pgdat(pgdat);
val->totalhigh = pgdat->node_zones[ZONE_HIGHMEM].present_pages;
val->freehigh = pgdat->node_zones[ZONE_HIGHMEM].free_pages;
@@ -1131,12 +1143,13 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
for (i = 0; i < MAX_NR_ZONES; i++)
totalpages += zones_size[i];
- pgdat->node_size = totalpages;
+ pgdat->node_spanned_pages = totalpages;
realtotalpages = totalpages;
if (zholes_size)
for (i = 0; i < MAX_NR_ZONES; i++)
realtotalpages -= zholes_size[i];
+ pgdat->node_present_pages = realtotalpages;
printk("On node %d totalpages: %lu\n", pgdat->node_id, realtotalpages);
}
@@ -1342,7 +1355,7 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat,
pgdat->node_start_pfn = node_start_pfn;
calculate_zone_totalpages(pgdat, zones_size, zholes_size);
if (!node_mem_map) {
- size = (pgdat->node_size + 1) * sizeof(struct page);
+ size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
node_mem_map = alloc_bootmem_node(pgdat, size);
}
pgdat->node_mem_map = node_mem_map;
diff --git a/mm/readahead.c b/mm/readahead.c
index d6fef1a3c124..179ba48d5e5c 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -363,9 +363,9 @@ page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra,
} else {
/*
* A miss - lseek, pagefault, pread, etc. Shrink the readahead
- * window by 25%.
+ * window.
*/
- ra->next_size -= ra->next_size / 4 + 2;
+ ra->next_size -= 2;
}
if ((long)ra->next_size > (long)max)
@@ -437,37 +437,6 @@ out:
return;
}
-/*
- * For mmap reads (typically executables) the access pattern is fairly random,
- * but somewhat ascending. So readaround favours pages beyond the target one.
- * We also boost the window size, as it can easily shrink due to misses.
- */
-void
-page_cache_readaround(struct address_space *mapping, struct file_ra_state *ra,
- struct file *filp, unsigned long offset)
-{
- if (ra->next_size != -1UL) {
- const unsigned long min = get_min_readahead(ra) * 2;
- unsigned long target;
- unsigned long backward;
-
- /*
- * If next_size is zero then leave it alone, because that's a
- * readahead startup state.
- */
- if (ra->next_size && ra->next_size < min)
- ra->next_size = min;
-
- target = offset;
- backward = ra->next_size / 4;
-
- if (backward > target)
- target = 0;
- else
- target -= backward;
- page_cache_readahead(mapping, ra, filp, target);
- }
-}
/*
* handle_ra_miss() is called when it is known that a page which should have
diff --git a/mm/shmem.c b/mm/shmem.c
index 73301cee3f41..e9d5042bc13b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -36,6 +36,7 @@
#include <linux/writeback.h>
#include <linux/vfs.h>
#include <linux/blkdev.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/div64.h>
@@ -507,7 +508,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
*/
change = VM_ACCT(attr->ia_size) - VM_ACCT(inode->i_size);
if (change > 0) {
- if (!vm_enough_memory(change))
+ if (security_vm_enough_memory(change))
return -ENOMEM;
} else if (attr->ia_size < inode->i_size) {
vm_unacct_memory(-change);
@@ -1139,7 +1140,7 @@ shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t
maxpos = inode->i_size;
if (maxpos < pos + count) {
maxpos = pos + count;
- if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
+ if (security_vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
err = -ENOMEM;
goto out;
}
@@ -1397,7 +1398,8 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, int mode)
return 0;
}
-static int shmem_create(struct inode *dir, struct dentry *dentry, int mode)
+static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
{
return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
}
@@ -1493,7 +1495,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
memcpy(info, symname, len);
inode->i_op = &shmem_symlink_inline_operations;
} else {
- if (!vm_enough_memory(VM_ACCT(1))) {
+ if (security_vm_enough_memory(VM_ACCT(1))) {
iput(inode);
return -ENOMEM;
}
@@ -1887,7 +1889,7 @@ struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
if (size > SHMEM_MAX_BYTES)
return ERR_PTR(-EINVAL);
- if ((flags & VM_ACCOUNT) && !vm_enough_memory(VM_ACCT(size)))
+ if ((flags & VM_ACCOUNT) && security_vm_enough_memory(VM_ACCT(size)))
return ERR_PTR(-ENOMEM);
error = -ENOMEM;
diff --git a/mm/slab.c b/mm/slab.c
index cad1bb2e8ebb..bee3dfdf8619 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -89,7 +89,12 @@
#include <linux/notifier.h>
#include <linux/kallsyms.h>
#include <linux/cpu.h>
+#include <linux/sysctl.h>
+#include <linux/module.h>
+
#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
/*
* DEBUG - 1 for kmem_cache_create() to honour; SLAB_DEBUG_INITIAL,
@@ -351,6 +356,34 @@ struct kmem_cache_s {
#define POISON_AFTER 0x6b /* for use-after-free poisoning */
#define POISON_END 0xa5 /* end-byte of poisoning */
+static inline int obj_dbghead(kmem_cache_t *cachep)
+{
+ if (cachep->flags & SLAB_RED_ZONE)
+ return BYTES_PER_WORD;
+ return 0;
+}
+
+static inline int obj_dbglen(kmem_cache_t *cachep)
+{
+ int len = 0;
+
+ if (cachep->flags & SLAB_RED_ZONE) {
+ len += 2*BYTES_PER_WORD;
+ }
+ if (cachep->flags & SLAB_STORE_USER) {
+ len += BYTES_PER_WORD;
+ }
+ return len;
+}
+#else
+static inline int obj_dbghead(kmem_cache_t *cachep)
+{
+ return 0;
+}
+static inline int obj_dbglen(kmem_cache_t *cachep)
+{
+ return 0;
+}
#endif
/*
@@ -430,6 +463,7 @@ struct list_head cache_chain;
* SLAB_RECLAIM_ACCOUNT turns this on per-slab
*/
atomic_t slab_reclaim_pages;
+EXPORT_SYMBOL(slab_reclaim_pages);
/*
* chicken and egg problem: delay the per-cpu array allocation
@@ -441,7 +475,7 @@ enum {
FULL
} g_cpucache_up;
-static struct timer_list reap_timers[NR_CPUS];
+static DEFINE_PER_CPU(struct timer_list, reap_timers);
static void reap_timer_fnc(unsigned long data);
@@ -491,7 +525,7 @@ static void __slab_error(const char *function, kmem_cache_t *cachep, char *msg)
*/
static void start_cpu_timer(int cpu)
{
- struct timer_list *rt = &reap_timers[cpu];
+ struct timer_list *rt = &per_cpu(reap_timers, cpu);
if (rt->function == NULL) {
init_timer(rt);
@@ -765,16 +799,45 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr)
}
#if DEBUG
-static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+
+#ifdef CONFIG_DEBUG_PAGEALLOC
+static void store_stackinfo(kmem_cache_t *cachep, unsigned long *addr, unsigned long caller)
{
- int size = cachep->objsize;
- if (cachep->flags & SLAB_RED_ZONE) {
- addr += BYTES_PER_WORD;
- size -= 2*BYTES_PER_WORD;
- }
- if (cachep->flags & SLAB_STORE_USER) {
- size -= BYTES_PER_WORD;
+ int size = cachep->objsize-obj_dbglen(cachep);
+
+ addr = (unsigned long *)&((char*)addr)[obj_dbghead(cachep)];
+
+ if (size < 5*sizeof(unsigned long))
+ return;
+
+ *addr++=0x12345678;
+ *addr++=caller;
+ *addr++=smp_processor_id();
+ size -= 3*sizeof(unsigned long);
+ {
+ unsigned long *sptr = &caller;
+ unsigned long svalue;
+
+ while (((long) sptr & (THREAD_SIZE-1)) != 0) {
+ svalue = *sptr++;
+ if (kernel_text_address(svalue)) {
+ *addr++=svalue;
+ size -= sizeof(unsigned long);
+ if (size <= sizeof(unsigned long))
+ break;
+ }
+ }
+
}
+ *addr++=0x87654321;
+}
+#endif
+
+static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
+{
+ int size = cachep->objsize-obj_dbglen(cachep);
+ addr = &((char*)addr)[obj_dbghead(cachep)];
+
memset(addr, val, size);
*(unsigned char *)(addr+size-1) = POISON_END;
}
@@ -796,15 +859,11 @@ static void *scan_poisoned_obj(unsigned char* addr, unsigned int size)
static void check_poison_obj(kmem_cache_t *cachep, void *addr)
{
- int size = cachep->objsize;
void *end;
- if (cachep->flags & SLAB_RED_ZONE) {
- addr += BYTES_PER_WORD;
- size -= 2*BYTES_PER_WORD;
- }
- if (cachep->flags & SLAB_STORE_USER) {
- size -= BYTES_PER_WORD;
- }
+ int size = cachep->objsize-obj_dbglen(cachep);
+
+ addr = &((char*)addr)[obj_dbghead(cachep)];
+
end = scan_poisoned_obj(addr, size);
if (end) {
int s;
@@ -858,8 +917,16 @@ static void slab_destroy (kmem_cache_t *cachep, struct slab *slabp)
void *objp = slabp->s_mem + cachep->objsize * i;
int objlen = cachep->objsize;
- if (cachep->flags & SLAB_POISON)
+ if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ if ((cachep->objsize%PAGE_SIZE)==0 && OFF_SLAB(cachep))
+ kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE,1);
+ else
+ check_poison_obj(cachep, objp);
+#else
check_poison_obj(cachep, objp);
+#endif
+ }
if (cachep->flags & SLAB_STORE_USER)
objlen -= BYTES_PER_WORD;
@@ -952,6 +1019,10 @@ kmem_cache_create (const char *name, size_t size, size_t offset,
}
#if FORCED_DEBUG
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ if (size < PAGE_SIZE-3*BYTES_PER_WORD && size > 128)
+ size = PAGE_SIZE-3*BYTES_PER_WORD;
+#endif
/*
* Enable redzoning and last user accounting, except
* - for caches with forced alignment: redzoning would violate the
@@ -1404,6 +1475,8 @@ static void cache_init_objs (kmem_cache_t * cachep,
slab_error(cachep, "constructor overwrote the"
" start of an object");
}
+ if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
+ kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
#else
if (cachep->ctor)
cachep->ctor(objp, cachep, ctor_flags);
@@ -1584,25 +1657,28 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp, v
* caller can perform a verify of its state (debugging).
* Called without the cache-lock held.
*/
- if (cachep->flags & SLAB_RED_ZONE) {
- cachep->ctor(objp+BYTES_PER_WORD,
+ cachep->ctor(objp+obj_dbghead(cachep),
cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
- } else {
- cachep->ctor(objp, cachep, SLAB_CTOR_CONSTRUCTOR|SLAB_CTOR_VERIFY);
- }
}
if (cachep->flags & SLAB_POISON && cachep->dtor) {
/* we want to cache poison the object,
* call the destruction callback
*/
- if (cachep->flags & SLAB_RED_ZONE)
- cachep->dtor(objp+BYTES_PER_WORD, cachep, 0);
- else
- cachep->dtor(objp, cachep, 0);
+ cachep->dtor(objp+obj_dbghead(cachep), cachep, 0);
}
- if (cachep->flags & SLAB_POISON)
+ if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) {
+ store_stackinfo(cachep, objp, POISON_AFTER);
+ kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
+ } else {
+ poison_obj(cachep, objp, POISON_AFTER);
+ }
+#else
poison_obj(cachep, objp, POISON_AFTER);
#endif
+ }
+#endif
return objp;
}
@@ -1617,6 +1693,7 @@ static inline void check_slabp(kmem_cache_t *cachep, struct slab *slabp)
for (i = slabp->free; i != BUFCTL_END; i = slab_bufctl(slabp)[i]) {
entries++;
BUG_ON(entries > cachep->num);
+ BUG_ON(i < 0 || i >= cachep->num);
}
BUG_ON(entries != cachep->num - slabp->inuse);
#endif
@@ -1746,9 +1823,16 @@ cache_alloc_debugcheck_after(kmem_cache_t *cachep,
if (!objp)
return objp;
- if (cachep->flags & SLAB_POISON) {
+ if (cachep->flags & SLAB_POISON) {
+#ifdef CONFIG_DEBUG_PAGEALLOC
+ if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep))
+ kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 1);
+ else
+ check_poison_obj(cachep, objp);
+#else
check_poison_obj(cachep, objp);
- poison_obj(cachep, objp, POISON_BEFORE);
+#endif
+ poison_obj(cachep, objp, POISON_BEFORE);
}
if (cachep->flags & SLAB_STORE_USER) {
objlen -= BYTES_PER_WORD;
@@ -2085,16 +2169,7 @@ free_percpu(const void *objp)
unsigned int kmem_cache_size(kmem_cache_t *cachep)
{
- unsigned int objlen = cachep->objsize;
-
-#if DEBUG
- if (cachep->flags & SLAB_RED_ZONE)
- objlen -= 2*BYTES_PER_WORD;
- if (cachep->flags & SLAB_STORE_USER)
- objlen -= BYTES_PER_WORD;
-#endif
-
- return objlen;
+ return cachep->objsize-obj_dbglen(cachep);
}
kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
@@ -2382,7 +2457,7 @@ next:
static void reap_timer_fnc(unsigned long data)
{
int cpu = smp_processor_id();
- struct timer_list *rt = &reap_timers[cpu];
+ struct timer_list *rt = &__get_cpu_var(reap_timers);
cache_reap();
mod_timer(rt, jiffies + REAPTIMEOUT_CPUC + cpu);
@@ -2626,3 +2701,70 @@ unsigned int ksize(const void *objp)
return size;
}
+void ptrinfo(unsigned long addr)
+{
+ struct page *page;
+
+ printk("Dumping data about address %p.\n", (void*)addr);
+ if (!virt_addr_valid((void*)addr)) {
+ printk("virt addr invalid.\n");
+ return;
+ }
+ do {
+ pgd_t *pgd = pgd_offset_k(addr);
+ pmd_t *pmd;
+ if (pgd_none(*pgd)) {
+ printk("No pgd.\n");
+ break;
+ }
+ pmd = pmd_offset(pgd, addr);
+ if (pmd_none(*pmd)) {
+ printk("No pmd.\n");
+ break;
+ }
+#ifdef CONFIG_X86
+ if (pmd_large(*pmd)) {
+ printk("Large page.\n");
+ break;
+ }
+#endif
+ printk("normal page, pte_val 0x%llx\n",
+ (unsigned long long)pte_val(*pte_offset_kernel(pmd, addr)));
+ } while(0);
+
+ page = virt_to_page((void*)addr);
+ printk("struct page at %p, flags %lxh.\n", page, page->flags);
+ if (PageSlab(page)) {
+ kmem_cache_t *c;
+ struct slab *s;
+ unsigned long flags;
+ int objnr;
+ void *objp;
+
+ c = GET_PAGE_CACHE(page);
+ printk("belongs to cache %s.\n",c->name);
+
+ spin_lock_irqsave(&c->spinlock, flags);
+ s = GET_PAGE_SLAB(page);
+ printk("slabp %p with %d inuse objects (from %d).\n",
+ s, s->inuse, c->num);
+ check_slabp(c,s);
+
+ objnr = (addr-(unsigned long)s->s_mem)/c->objsize;
+ objp = s->s_mem+c->objsize*objnr;
+ printk("points into object no %d, starting at %p, len %d.\n",
+ objnr, objp, c->objsize);
+ if (objnr >= c->num) {
+ printk("Bad obj number.\n");
+ } else {
+ kernel_map_pages(virt_to_page(objp), c->objsize/PAGE_SIZE, 1);
+
+ printk("redzone: %lxh/%lxh/%lxh.\n",
+ ((unsigned long*)objp)[0],
+ ((unsigned long*)(objp+c->objsize))[-2],
+ ((unsigned long*)(objp+c->objsize))[-1]);
+ }
+ spin_unlock_irqrestore(&c->spinlock, flags);
+
+ }
+}
diff --git a/mm/swap.c b/mm/swap.c
index 5818b0a5a72d..37302961e371 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -20,6 +20,7 @@
#include <linux/pagemap.h>
#include <linux/pagevec.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/mm_inline.h>
#include <linux/buffer_head.h> /* for try_to_release_page() */
#include <linux/percpu.h>
@@ -370,6 +371,7 @@ void vm_acct_memory(long pages)
}
preempt_enable();
}
+EXPORT_SYMBOL(vm_acct_memory);
#endif
diff --git a/mm/swapfile.c b/mm/swapfile.c
index bdfd09be8d4c..bc31505b689f 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -20,7 +20,9 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/rmap-locking.h>
+#include <linux/security.h>
#include <asm/pgtable.h>
#include <linux/swapops.h>
@@ -30,6 +32,8 @@ unsigned int nr_swapfiles;
int total_swap_pages;
static int swap_overflow;
+EXPORT_SYMBOL(total_swap_pages);
+
static const char Bad_file[] = "Bad swap file entry ";
static const char Unused_file[] = "Unused swap file entry ";
static const char Bad_offset[] = "Bad swap offset entry ";
@@ -1042,7 +1046,7 @@ asmlinkage long sys_swapoff(const char __user * specialfile)
swap_list_unlock();
goto out_dput;
}
- if (vm_enough_memory(p->pages))
+ if (!security_vm_enough_memory(p->pages))
vm_unacct_memory(p->pages);
else {
err = -ENOMEM;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 2040a73db165..1953785a0cea 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -632,6 +632,7 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event,
struct net_proto_family hci_sock_family_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.create = hci_sock_create,
};
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 2a3eff6b4372..e0aafca1b78d 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -878,6 +878,7 @@ static struct proto_ops rfcomm_sock_ops = {
static struct net_proto_family rfcomm_sock_family_ops = {
.family = PF_BLUETOOTH,
+ .owner = THIS_MODULE,
.create = rfcomm_sock_create
};
diff --git a/net/core/dev.c b/net/core/dev.c
index 5102b235b57c..0605391589ad 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1712,7 +1712,7 @@ out:
softnet_break:
netdev_rx_stat[this_cpu].time_squeeze++;
- __cpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ);
+ __raise_softirq_irqoff(NET_RX_SOFTIRQ);
goto out;
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 64b97aec0312..f249d4388e36 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -594,7 +594,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
if (err)
goto fail;
- err = permission(nd.dentry->d_inode,MAY_WRITE);
+ err = permission(nd.dentry->d_inode,MAY_WRITE, &nd);
if (err)
goto put_fail;
diff --git a/security/capability.c b/security/capability.c
index e01bc5271c36..cff54dd440fc 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -15,6 +15,9 @@
#include <linux/security.h>
#include <linux/file.h>
#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
#include <linux/smp_lock.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
@@ -275,6 +278,65 @@ int cap_syslog (int type)
return 0;
}
+/*
+ * Check that a process has enough memory to allocate a new virtual
+ * mapping. 0 means there is enough memory for the allocation to
+ * succeed and -ENOMEM implies there is not.
+ *
+ * We currently support three overcommit policies, which are set via the
+ * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-acounting
+ *
+ * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
+ * Additional code 2002 Jul 20 by Robert Love.
+ */
+int cap_vm_enough_memory(long pages)
+{
+ unsigned long free, allowed;
+
+ vm_acct_memory(pages);
+
+ /*
+ * Sometimes we want to use more memory than we have
+ */
+ if (sysctl_overcommit_memory == 1)
+ return 0;
+
+ if (sysctl_overcommit_memory == 0) {
+ free = get_page_cache_size();
+ free += nr_free_pages();
+ free += nr_swap_pages;
+
+ /*
+ * Any slabs which are created with the
+ * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+ * which are reclaimable, under pressure. The dentry
+ * cache and most inode caches should fall into this
+ */
+ free += atomic_read(&slab_reclaim_pages);
+
+ /*
+ * Leave the last 3% for root
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ free -= free / 32;
+
+ if (free > pages)
+ return 0;
+ vm_unacct_memory(pages);
+ return -ENOMEM;
+ }
+
+ allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+ allowed += total_swap_pages;
+
+ if (atomic_read(&vm_committed_space) < allowed)
+ return 0;
+
+ vm_unacct_memory(pages);
+
+ return -ENOMEM;
+}
+
EXPORT_SYMBOL(cap_capable);
EXPORT_SYMBOL(cap_ptrace);
EXPORT_SYMBOL(cap_capget);
@@ -286,6 +348,7 @@ EXPORT_SYMBOL(cap_bprm_secureexec);
EXPORT_SYMBOL(cap_task_post_setuid);
EXPORT_SYMBOL(cap_task_reparent_to_init);
EXPORT_SYMBOL(cap_syslog);
+EXPORT_SYMBOL(cap_vm_enough_memory);
#ifdef CONFIG_SECURITY
@@ -307,6 +370,8 @@ static struct security_operations capability_ops = {
.task_reparent_to_init = cap_task_reparent_to_init,
.syslog = cap_syslog,
+
+ .vm_enough_memory = cap_vm_enough_memory,
};
#if defined(CONFIG_SECURITY_CAPABILITIES_MODULE)
diff --git a/security/dummy.c b/security/dummy.c
index a4307e78a168..76c6560a76c2 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -17,6 +17,9 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/mman.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
#include <linux/security.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
@@ -97,6 +100,54 @@ static int dummy_syslog (int type)
return 0;
}
+static int dummy_vm_enough_memory(long pages)
+{
+ unsigned long free, allowed;
+
+ vm_acct_memory(pages);
+
+ /*
+ * Sometimes we want to use more memory than we have
+ */
+ if (sysctl_overcommit_memory == 1)
+ return 0;
+
+ if (sysctl_overcommit_memory == 0) {
+ free = get_page_cache_size();
+ free += nr_free_pages();
+ free += nr_swap_pages;
+
+ /*
+ * Any slabs which are created with the
+ * SLAB_RECLAIM_ACCOUNT flag claim to have contents
+ * which are reclaimable, under pressure. The dentry
+ * cache and most inode caches should fall into this
+ */
+ free += atomic_read(&slab_reclaim_pages);
+
+ /*
+ * Leave the last 3% for root
+ */
+ if (current->euid)
+ free -= free / 32;
+
+ if (free > pages)
+ return 0;
+ vm_unacct_memory(pages);
+ return -ENOMEM;
+ }
+
+ allowed = totalram_pages * sysctl_overcommit_ratio / 100;
+ allowed += total_swap_pages;
+
+ if (atomic_read(&vm_committed_space) < allowed)
+ return 0;
+
+ vm_unacct_memory(pages);
+
+ return -ENOMEM;
+}
+
static int dummy_bprm_alloc_security (struct linux_binprm *bprm)
{
return 0;
@@ -793,6 +844,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, quota_on);
set_to_dummy_if_null(ops, sysctl);
set_to_dummy_if_null(ops, syslog);
+ set_to_dummy_if_null(ops, vm_enough_memory);
set_to_dummy_if_null(ops, bprm_alloc_security);
set_to_dummy_if_null(ops, bprm_free_security);
set_to_dummy_if_null(ops, bprm_compute_creds);